Esempio n. 1
0
 def test_unerased_pointers_in_short_preamble(self):
     from pypy.rlib.rerased import new_erasing_pair
     from pypy.rpython.lltypesystem import lltype
     class A(object):
         def __init__(self, val):
             self.val = val
     erase_A, unerase_A = new_erasing_pair('A')
     erase_TP, unerase_TP = new_erasing_pair('TP')
     TP = lltype.GcArray(lltype.Signed)
     myjitdriver = JitDriver(greens = [], reds = ['n', 'm', 'i', 'j', 'sa', 'p'])
     def f(n, m, j):
         i = sa = 0
         p = erase_A(A(7))
         while i < n:
             myjitdriver.jit_merge_point(n=n, m=m, i=i, j=j, sa=sa, p=p)
             if i < m:
                 sa += unerase_A(p).val
             elif i == m:
                 a = lltype.malloc(TP, 5)
                 a[0] = 42
                 p = erase_TP(a)
             else:
                 sa += unerase_TP(p)[0]
             sa += A(i).val
             assert n>0 and m>0
             i += j
         return sa
     res = self.meta_interp(f, [20, 10, 1])
     assert res == f(20, 10, 1)
Esempio n. 2
0
    def test_unerased_pointers_in_short_preamble(self):
        from pypy.rlib.rerased import new_erasing_pair
        from pypy.rpython.lltypesystem import lltype

        class A(object):
            def __init__(self, val):
                self.val = val

        erase_A, unerase_A = new_erasing_pair('A')
        erase_TP, unerase_TP = new_erasing_pair('TP')
        TP = lltype.GcArray(lltype.Signed)
        myjitdriver = JitDriver(greens=[],
                                reds=['n', 'm', 'i', 'j', 'sa', 'p'])

        def f(n, m, j):
            i = sa = 0
            p = erase_A(A(7))
            while i < n:
                myjitdriver.jit_merge_point(n=n, m=m, i=i, j=j, sa=sa, p=p)
                if i < m:
                    sa += unerase_A(p).val
                elif i == m:
                    a = lltype.malloc(TP, 5)
                    a[0] = 42
                    p = erase_TP(a)
                else:
                    sa += unerase_TP(p)[0]
                sa += A(i).val
                assert n > 0 and m > 0
                i += j
            return sa

        res = self.meta_interp(f, [20, 10, 1])
        assert res == f(20, 10, 1)
Esempio n. 3
0
class FloatListStrategy(AbstractUnwrappedStrategy, ListStrategy):
    _none_value = 0.0
    _applevel_repr = "float"

    def wrap(self, floatval):
        return self.space.wrap(floatval)

    def unwrap(self, w_float):
        return self.space.float_w(w_float)

    erase, unerase = rerased.new_erasing_pair("float")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def is_correct_type(self, w_obj):
        return is_W_FloatObject(w_obj)

    def list_is_correct_type(self, w_list):
        return w_list.strategy is self.space.fromcache(FloatListStrategy)

    def sort(self, w_list, reverse):
        l = self.unerase(w_list.lstorage)
        sorter = FloatSort(l, len(l))
        sorter.sort()
        if reverse:
            l.reverse()
Esempio n. 4
0
class ObjectListStrategy(AbstractUnwrappedStrategy, ListStrategy):
    _none_value = None
    _applevel_repr = "object"

    def unwrap(self, w_obj):
        return w_obj

    def wrap(self, item):
        return item

    erase, unerase = rerased.new_erasing_pair("object")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def is_correct_type(self, w_obj):
        return True

    def list_is_correct_type(self, w_list):
        return w_list.strategy is self.space.fromcache(ObjectListStrategy)

    def init_from_list_w(self, w_list, list_w):
        w_list.lstorage = self.erase(list_w)

    def contains(self, w_list, w_obj):
        return ListStrategy.contains(self, w_list, w_obj)

    def getitems(self, w_list):
        return self.unerase(w_list.lstorage)
Esempio n. 5
0
class ObjectDictStrategy(AbstractTypedStrategy, DictStrategy):

    erase, unerase = rerased.new_erasing_pair("object")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def wrap(self, unwrapped):
        return unwrapped

    def unwrap(self, wrapped):
        return wrapped

    def is_correct_type(self, w_obj):
        return True

    def get_empty_storage(self):
       new_dict = r_dict(self.space.eq_w, self.space.hash_w,
                         force_non_null=True)
       return self.erase(new_dict)

    def _never_equal_to(self, w_lookup_type):
        return False

    def iter(self, w_dict):
        return ObjectIteratorImplementation(self.space, self, w_dict)

    def w_keys(self, w_dict):
        return self.space.newlist(self.unerase(w_dict.dstorage).keys())
Esempio n. 6
0
class StringListStrategy(AbstractUnwrappedStrategy, ListStrategy):
    _none_value = None
    _applevel_repr = "str"

    def wrap(self, stringval):
        return self.space.wrap(stringval)

    def unwrap(self, w_string):
        return self.space.str_w(w_string)

    erase, unerase = rerased.new_erasing_pair("string")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def is_correct_type(self, w_obj):
        return is_W_StringObject(w_obj)

    def list_is_correct_type(self, w_list):
        return w_list.strategy is self.space.fromcache(StringListStrategy)

    def sort(self, w_list, reverse):
        l = self.unerase(w_list.lstorage)
        sorter = StringSort(l, len(l))
        sorter.sort()
        if reverse:
            l.reverse()

    def getitems_str(self, w_list):
        return self.unerase(w_list.lstorage)
Esempio n. 7
0
class DictProxyStrategy(DictStrategy):

    erase, unerase = rerased.new_erasing_pair("dictproxy")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def __init__(w_self, space):
        DictStrategy.__init__(w_self, space)

    def getitem(self, w_dict, w_key):
        space = self.space
        w_lookup_type = space.type(w_key)
        if (space.is_w(w_lookup_type, space.w_str) or  # Most common path first
                space.abstract_issubclass_w(w_lookup_type, space.w_str)):
            return self.getitem_str(w_dict, space.str_w(w_key))
        elif space.abstract_issubclass_w(w_lookup_type, space.w_unicode):
            try:
                w_key = space.str(w_key)
            except OperationError, e:
                if not e.match(space, space.w_UnicodeEncodeError):
                    raise
                # non-ascii unicode is never equal to a byte string
                return None
            return self.getitem_str(w_dict, space.str_w(w_key))
        else:
Esempio n. 8
0
 def test_opaque_list(self):
     from pypy.rlib.rerased import new_erasing_pair
     erase, unerase = new_erasing_pair("test_opaque_list")
     def fn(n, ca, cb):
         l1 = [n]
         l2 = [n]
         a1 = erase(l1)
         a2 = erase(l1)
         a = a1
         if ca:
             a = a2
             if n < -100:
                 unerase(a).append(5)
         b = a1
         if cb:
             b = a
         return unerase(a)[0] + unerase(b)[0]
     res = self.interp_operations(fn, [7, 0, 1])
     assert res == 7 * 2
     self.check_operations_history(getarrayitem_gc=0,
             getfield_gc=0)
     res = self.interp_operations(fn, [-7, 1, 1])
     assert res == -7 * 2
     self.check_operations_history(getarrayitem_gc=0,
             getfield_gc=0)
Esempio n. 9
0
class IntegerSetStrategy(AbstractUnwrappedSetStrategy, SetStrategy):
    erase, unerase = rerased.new_erasing_pair("integer")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def get_empty_storage(self):
        return self.erase({})

    def get_empty_dict(self):
        return {}

    def listview_int(self, w_set):
        return self.unerase(w_set.sstorage).keys()

    def is_correct_type(self, w_key):
        from pypy.objspace.std.intobject import W_IntObject
        return type(w_key) is W_IntObject

    def may_contain_equal_elements(self, strategy):
        if strategy is self.space.fromcache(StringSetStrategy):
            return False
        if strategy is self.space.fromcache(EmptySetStrategy):
            return False
        return True

    def unwrap(self, w_item):
        return self.space.int_w(w_item)

    def wrap(self, item):
        return self.space.wrap(item)

    def iter(self, w_set):
        return IntegerIteratorImplementation(self.space, self, w_set)
Esempio n. 10
0
class IntDictStrategy(AbstractTypedStrategy, DictStrategy):
    erase, unerase = rerased.new_erasing_pair("int")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def wrap(self, unwrapped):
        return self.space.wrap(unwrapped)

    def unwrap(self, wrapped):
        return self.space.int_w(wrapped)

    def get_empty_storage(self):
        return self.erase({})

    def is_correct_type(self, w_obj):
        space = self.space
        return space.is_w(space.type(w_obj), space.w_int)

    def _never_equal_to(self, w_lookup_type):
        space = self.space
        # XXX there are many more types
        return (space.is_w(w_lookup_type, space.w_NoneType) or
                space.is_w(w_lookup_type, space.w_str) or
                space.is_w(w_lookup_type, space.w_unicode)
                )

    def iter(self, w_dict):
        return IntIteratorImplementation(self.space, self, w_dict)

    def listview_int(self, w_dict):
        return self.unerase(w_dict.dstorage).keys()
Esempio n. 11
0
    def define_erased(cls):
        from pypy.rlib import rerased
        erase, unerase = rerased.new_erasing_pair("test")
        class Unrelated(object):
            pass

        u = Unrelated()
        u.tagged = True
        u.x = rerased.erase_int(41)
        class A(object):
            pass
        def fn():
            n = 1
            while n >= 0:
                if u.tagged:
                    n = rerased.unerase_int(u.x)
                    a = A()
                    a.n = n - 1
                    u.x = erase(a)
                    u.tagged = False
                else:
                    n = unerase(u.x).n
                    u.x = rerased.erase_int(n - 1)
                    u.tagged = True
        def func():
            rgc.collect() # check that a prebuilt erased integer doesn't explode
            u.x = rerased.erase_int(1000)
            u.tagged = True
            fn()
            return 1
        return func
Esempio n. 12
0
class StringDictStrategy(AbstractTypedStrategy, DictStrategy):

    erase, unerase = rerased.new_erasing_pair("string")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def wrap(self, unwrapped):
        return self.space.wrap(unwrapped)

    def unwrap(self, wrapped):
        return self.space.str_w(wrapped)

    def is_correct_type(self, w_obj):
        space = self.space
        return space.is_w(space.type(w_obj), space.w_str)

    def get_empty_storage(self):
        res = {}
        mark_dict_non_null(res)
        return self.erase(res)

    def _never_equal_to(self, w_lookup_type):
        return _never_equal_to_string(self.space, w_lookup_type)

    def setitem_str(self, w_dict, key, w_value):
        assert key is not None
        self.unerase(w_dict.dstorage)[key] = w_value

    def getitem(self, w_dict, w_key):
        space = self.space
        # -- This is called extremely often.  Hack for performance --
        if type(w_key) is space.StringObjectCls:
            return self.getitem_str(w_dict, w_key.unwrap(space))
        # -- End of performance hack --
        return AbstractTypedStrategy.getitem(self, w_dict, w_key)

    def getitem_str(self, w_dict, key):
        assert key is not None
        return self.unerase(w_dict.dstorage).get(key, None)

    def listview_str(self, w_dict):
        return self.unerase(w_dict.dstorage).keys()

    def iter(self, w_dict):
        return StrIteratorImplementation(self.space, self, w_dict)

    def w_keys(self, w_dict):
        return self.space.newlist_str(self.listview_str(w_dict))
Esempio n. 13
0
class DictProxyStrategy(DictStrategy):

    erase, unerase = rerased.new_erasing_pair("dictproxy")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def __init__(w_self, space):
        DictStrategy.__init__(w_self, space)

    def getitem(self, w_dict, w_key):
        space = self.space
        w_lookup_type = space.type(w_key)
        if space.is_w(w_lookup_type, space.w_str):
            return self.getitem_str(w_dict, space.str_w(w_key))
        else:
            return None

    def getitem_str(self, w_dict, key):
        return self.unerase(w_dict.dstorage).getdictvalue(self.space, key)

    def setitem(self, w_dict, w_key, w_value):
        space = self.space
        if space.is_w(space.type(w_key), space.w_str):
            self.setitem_str(w_dict, 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 setitem_str(self, w_dict, key, w_value):
        w_type = self.unerase(w_dict.dstorage)
        try:
            w_type.setdictvalue(self.space, key, w_value)
        except OperationError, e:
            if not e.match(self.space, self.space.w_TypeError):
                raise
            if not w_type.is_cpytype():
                raise
            # xxx obscure workaround: allow cpyext to write to type->tp_dict.
            # xxx like CPython, we assume that this is only done early after
            # xxx the type is created, and we don't invalidate any cache.
            w_type.dict_w[key] = w_value
Esempio n. 14
0
class ObjectSetStrategy(AbstractUnwrappedSetStrategy, SetStrategy):
    erase, unerase = rerased.new_erasing_pair("object")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def get_empty_storage(self):
        return self.erase(self.get_empty_dict())

    def get_empty_dict(self):
        return newset(self.space)

    def is_correct_type(self, w_key):
        return True

    def may_contain_equal_elements(self, strategy):
        if strategy is self.space.fromcache(EmptySetStrategy):
            return False
        return True

    def unwrap(self, w_item):
        return w_item

    def wrap(self, item):
        return item

    def iter(self, w_set):
        return RDictIteratorImplementation(self.space, self, w_set)

    def update(self, w_set, w_other):
        d_obj = self.unerase(w_set.sstorage)
        w_iterator = w_other.iter()
        while True:
            w_item = w_iterator.next_entry()
            if w_item is None:
                break
            d_obj[w_item] = None
Esempio n. 15
0
class RangeListStrategy(ListStrategy):
    """RangeListStrategy is used when a list is created using the range method.
    The storage is a tuple containing only three integers start, step and length
    and elements are calculated based on these values.
    On any operation destroying the range (inserting, appending non-ints)
    the strategy is switched to IntegerListStrategy."""

    _applevel_repr = "range"

    def switch_to_integer_strategy(self, w_list):
        items = self._getitems_range(w_list, False)
        strategy = w_list.strategy = self.space.fromcache(IntegerListStrategy)
        w_list.lstorage = strategy.erase(items)

    def wrap(self, intval):
        return self.space.wrap(intval)

    def unwrap(self, w_int):
        return self.space.int_w(w_int)

    def init_from_list_w(self, w_list, list_w):
        raise NotImplementedError

    erase, unerase = rerased.new_erasing_pair("range")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def clone(self, w_list):
        storage = w_list.lstorage  # lstorage is tuple, no need to clone
        w_clone = W_ListObject.from_storage_and_strategy(
            self.space, storage, self)
        return w_clone

    def copy_into(self, w_list, w_other):
        w_other.strategy = self
        w_other.lstorage = w_list.lstorage

    def contains(self, w_list, w_obj):
        if is_W_IntObject(w_obj):
            start, step, length = self.unerase(w_list.lstorage)
            obj = self.unwrap(w_obj)
            i = start
            if step > 0 and start <= obj <= start + (length - 1) * step and (
                    start - obj) % step == 0:
                return True
            elif step < 0 and start + (length - 1) * step <= obj <= start and (
                    start - obj) % step == 0:
                return True
            else:
                return False
        return ListStrategy.contains(self, w_list, w_obj)

    def length(self, w_list):
        return self.unerase(w_list.lstorage)[2]

    def _getitem_unwrapped(self, w_list, i):
        v = self.unerase(w_list.lstorage)
        start = v[0]
        step = v[1]
        length = v[2]
        if i < 0:
            i += length
            if i < 0:
                raise IndexError
        elif i >= length:
            raise IndexError
        return start + i * step

    def getitem(self, w_list, i):
        return self.wrap(self._getitem_unwrapped(w_list, i))

    def getitems_copy(self, w_list):
        return self._getitems_range(w_list, True)

    def getstorage_copy(self, w_list):
        # tuple is unmutable
        return w_list.lstorage

    @specialize.arg(2)
    def _getitems_range(self, w_list, wrap_items):
        l = self.unerase(w_list.lstorage)
        start = l[0]
        step = l[1]
        length = l[2]
        if wrap_items:
            r = [None] * length
        else:
            r = [0] * length
        i = start
        n = 0
        while n < length:
            if wrap_items:
                r[n] = self.wrap(i)
            else:
                r[n] = i
            i += step
            n += 1

        return r

    @jit.dont_look_inside
    def getitems_fixedsize(self, w_list):
        return self._getitems_range_unroll(w_list, True)

    def getitems_unroll(self, w_list):
        return self._getitems_range_unroll(w_list, True)

    _getitems_range_unroll = jit.unroll_safe(
        func_with_new_name(_getitems_range, "_getitems_range_unroll"))

    def getslice(self, w_list, start, stop, step, length):
        v = self.unerase(w_list.lstorage)
        old_start = v[0]
        old_step = v[1]
        old_length = v[2]

        new_start = self._getitem_unwrapped(w_list, start)
        new_step = old_step * step
        return make_range_list(self.space, new_start, new_step, length)

    def append(self, w_list, w_item):
        if is_W_IntObject(w_item):
            l = self.unerase(w_list.lstorage)
            step = l[1]
            last_in_range = self._getitem_unwrapped(w_list, -1)
            if self.unwrap(w_item) - step == last_in_range:
                new = self.erase((l[0], l[1], l[2] + 1))
                w_list.lstorage = new
                return

            self.switch_to_integer_strategy(w_list)
        else:
            w_list.switch_to_object_strategy()
        w_list.append(w_item)

    def inplace_mul(self, w_list, times):
        self.switch_to_integer_strategy(w_list)
        w_list.inplace_mul(times)

    def deleteslice(self, w_list, start, step, slicelength):
        self.switch_to_integer_strategy(w_list)
        w_list.deleteslice(start, step, slicelength)

    def pop_end(self, w_list):
        start, step, length = self.unerase(w_list.lstorage)
        w_result = self.wrap(start + (length - 1) * step)
        new = self.erase((start, step, length - 1))
        w_list.lstorage = new
        return w_result

    def pop(self, w_list, index):
        l = self.unerase(w_list.lstorage)
        start = l[0]
        step = l[1]
        length = l[2]
        if index == 0:
            w_result = self.wrap(start)
            new = self.erase((start + step, step, length - 1))
            w_list.lstorage = new
            return w_result
        elif index == length - 1:
            return self.pop_end(w_list)
        else:
            self.switch_to_integer_strategy(w_list)
            return w_list.pop(index)

    def setitem(self, w_list, index, w_item):
        self.switch_to_integer_strategy(w_list)
        w_list.setitem(index, w_item)

    def setslice(self, w_list, start, step, slicelength, sequence_w):
        self.switch_to_integer_strategy(w_list)
        w_list.setslice(start, step, slicelength, sequence_w)

    def sort(self, w_list, reverse):
        start, step, length = self.unerase(w_list.lstorage)
        if step > 0 and reverse or step < 0 and not reverse:
            start = start + step * (length - 1)
            step = step * (-1)
        else:
            return
        w_list.lstorage = self.erase((start, step, length))

    def insert(self, w_list, index, w_item):
        self.switch_to_integer_strategy(w_list)
        w_list.insert(index, w_item)

    def extend(self, w_list, items_w):
        self.switch_to_integer_strategy(w_list)
        w_list.extend(items_w)

    def reverse(self, w_list):
        v = self.unerase(w_list.lstorage)
        last = self._getitem_unwrapped(w_list, -1)
        length = v[2]
        skip = v[1]
        new = self.erase((last, -skip, length))
        w_list.lstorage = new
Esempio n. 16
0
class EmptySetStrategy(SetStrategy):

    erase, unerase = rerased.new_erasing_pair("empty")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def get_empty_storage(self):
        return self.erase(None)

    def is_correct_type(self, w_key):
        return False

    def length(self, w_set):
        return 0

    def clear(self, w_set):
        pass

    def copy_real(self, w_set):
        storage = self.erase(None)
        clone = w_set.from_storage_and_strategy(storage, self)
        return clone

    def add(self, w_set, w_key):
        if type(w_key) is W_IntObject:
            strategy = self.space.fromcache(IntegerSetStrategy)
        elif type(w_key) is W_StringObject:
            strategy = self.space.fromcache(StringSetStrategy)
        else:
            strategy = self.space.fromcache(ObjectSetStrategy)
        w_set.strategy = strategy
        w_set.sstorage = strategy.get_empty_storage()
        w_set.add(w_key)

    def remove(self, w_set, w_item):
        return False

    def getdict_w(self, w_set):
        return newset(self.space)

    def get_storage_copy(self, w_set):
        return w_set.sstorage

    def getkeys(self, w_set):
        return []

    def has_key(self, w_set, w_key):
        return False

    def equals(self, w_set, w_other):
        if w_other.strategy is self or w_other.length() == 0:
            return True
        return False

    def difference(self, w_set, w_other):
        return w_set.copy_real()

    def difference_update(self, w_set, w_other):
        pass

    def intersect(self, w_set, w_other):
        return w_set.copy_real()

    def intersect_update(self, w_set, w_other):
        pass

    def isdisjoint(self, w_set, w_other):
        return True

    def issubset(self, w_set, w_other):
        return True

    def symmetric_difference(self, w_set, w_other):
        return w_other.copy_real()

    def symmetric_difference_update(self, w_set, w_other):
        w_set.strategy = w_other.strategy
        w_set.sstorage = w_other.get_storage_copy()

    def update(self, w_set, w_other):
        w_set.strategy = w_other.strategy
        w_set.sstorage = w_other.get_storage_copy()

    def iter(self, w_set):
        return EmptyIteratorImplementation(self.space, self, w_set)

    def popitem(self, w_set):
        raise OperationError(self.space.w_KeyError,
                             self.space.wrap('pop from an empty set'))
Esempio n. 17
0
class KwargsDictStrategy(DictStrategy):
    erase, unerase = rerased.new_erasing_pair("kwargsdict")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def wrap(self, key):
        return self.space.wrap(key)

    def unwrap(self, wrapped):
        return self.space.str_w(wrapped)

    def get_empty_storage(self):
        d = ([], [])
        return self.erase(d)

    def is_correct_type(self, w_obj):
        space = self.space
        return space.is_w(space.type(w_obj), space.w_str)

    def _never_equal_to(self, w_lookup_type):
        return False

    def iter(self, w_dict):
        return KwargsDictIterator(self.space, self, w_dict)

    def w_keys(self, w_dict):
        return self.space.newlist(
            [self.space.wrap(key) for key in self.unerase(w_dict.dstorage)[0]])

    def setitem(self, w_dict, w_key, w_value):
        space = self.space
        if self.is_correct_type(w_key):
            self.setitem_str(w_dict, self.unwrap(w_key), w_value)
            return
        else:
            self.switch_to_object_strategy(w_dict)
            w_dict.setitem(w_key, w_value)

    def setitem_str(self, w_dict, key, w_value):
        self._setitem_str_indirection(w_dict, key, w_value)

    @jit.look_inside_iff(lambda self, w_dict, key, w_value: jit.isconstant(
        self.length(w_dict)) and jit.isconstant(key))
    def _setitem_str_indirection(self, w_dict, key, w_value):
        keys, values_w = self.unerase(w_dict.dstorage)
        result = []
        for i in range(len(keys)):
            if keys[i] == key:
                values_w[i] = w_value
                break
        else:
            # limit the size so that the linear searches don't become too long
            if len(keys) >= 16:
                self.switch_to_string_strategy(w_dict)
                w_dict.setitem_str(key, w_value)
            else:
                keys.append(key)
                values_w.append(w_value)

    def setdefault(self, w_dict, w_key, w_default):
        # XXX could do better, but is it worth it?
        self.switch_to_object_strategy(w_dict)
        return w_dict.setdefault(w_key, w_default)

    def delitem(self, w_dict, w_key):
        # XXX could do better, but is it worth it?
        self.switch_to_object_strategy(w_dict)
        return w_dict.delitem(w_key)

    def length(self, w_dict):
        return len(self.unerase(w_dict.dstorage)[0])

    def getitem_str(self, w_dict, key):
        return self._getitem_str_indirection(w_dict, key)

    @jit.look_inside_iff(lambda self, w_dict, key: jit.isconstant(
        self.length(w_dict)) and jit.isconstant(key))
    def _getitem_str_indirection(self, w_dict, key):
        keys, values_w = self.unerase(w_dict.dstorage)
        result = []
        for i in range(len(keys)):
            if keys[i] == key:
                return values_w[i]
        return None

    def getitem(self, w_dict, w_key):
        space = self.space
        if self.is_correct_type(w_key):
            return self.getitem_str(w_dict, self.unwrap(w_key))
        elif self._never_equal_to(space.type(w_key)):
            return None
        else:
            self.switch_to_object_strategy(w_dict)
            return w_dict.getitem(w_key)

    def w_keys(self, w_dict):
        l = self.unerase(w_dict.dstorage)[0]
        return self.space.newlist_str(l[:])

    def values(self, w_dict):
        return self.unerase(w_dict.dstorage)[1][:]  # to make non-resizable

    def items(self, w_dict):
        space = self.space
        keys, values_w = self.unerase(w_dict.dstorage)
        result = []
        for i in range(len(keys)):
            result.append(space.newtuple([self.wrap(keys[i]), values_w[i]]))
        return result

    def popitem(self, w_dict):
        keys, values_w = self.unerase(w_dict.dstorage)
        key = keys.pop()
        w_value = values_w.pop()
        return (self.wrap(key), w_value)

    def clear(self, w_dict):
        w_dict.dstorage = self.get_empty_storage()

    def switch_to_object_strategy(self, w_dict):
        strategy = self.space.fromcache(ObjectDictStrategy)
        keys, values_w = self.unerase(w_dict.dstorage)
        d_new = strategy.unerase(strategy.get_empty_storage())
        for i in range(len(keys)):
            d_new[self.wrap(keys[i])] = values_w[i]
        w_dict.strategy = strategy
        w_dict.dstorage = strategy.erase(d_new)

    def switch_to_string_strategy(self, w_dict):
        strategy = self.space.fromcache(StringDictStrategy)
        keys, values_w = self.unerase(w_dict.dstorage)
        storage = strategy.get_empty_storage()
        d_new = strategy.unerase(storage)
        for i in range(len(keys)):
            d_new[keys[i]] = values_w[i]
        w_dict.strategy = strategy
        w_dict.dstorage = storage

    def view_as_kwargs(self, w_dict):
        return self.unerase(w_dict.dstorage)
Esempio n. 18
0
class MapDictStrategy(DictStrategy):

    erase, unerase = rerased.new_erasing_pair("map")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def __init__(self, space):
        self.space = space

    def switch_to_object_strategy(self, w_dict):
        w_obj = self.unerase(w_dict.dstorage)
        strategy = self.space.fromcache(ObjectDictStrategy)
        dict_w = strategy.unerase(strategy.get_empty_storage())
        w_dict.strategy = strategy
        w_dict.dstorage = strategy.erase(dict_w)
        assert w_obj.getdict(self.space) is w_dict
        materialize_r_dict(self.space, w_obj, dict_w)

    def getitem(self, w_dict, w_key):
        space = self.space
        w_lookup_type = space.type(w_key)
        if space.is_w(w_lookup_type, space.w_str):
            return self.getitem_str(w_dict, space.str_w(w_key))
        elif _never_equal_to_string(space, w_lookup_type):
            return None
        else:
            self.switch_to_object_strategy(w_dict)
            return w_dict.getitem(w_key)

    def getitem_str(self, w_dict, key):
        w_obj = self.unerase(w_dict.dstorage)
        return w_obj.getdictvalue(self.space, key)

    def setitem_str(self, w_dict, key, w_value):
        w_obj = self.unerase(w_dict.dstorage)
        flag = w_obj.setdictvalue(self.space, key, w_value)
        assert flag

    def setitem(self, w_dict, w_key, w_value):
        space = self.space
        if space.is_w(space.type(w_key), space.w_str):
            self.setitem_str(w_dict, self.space.str_w(w_key), w_value)
        else:
            self.switch_to_object_strategy(w_dict)
            w_dict.setitem(w_key, w_value)

    def setdefault(self, w_dict, w_key, w_default):
        space = self.space
        if space.is_w(space.type(w_key), space.w_str):
            key = space.str_w(w_key)
            w_result = self.getitem_str(w_dict, key)
            if w_result is not None:
                return w_result
            self.setitem_str(w_dict, key, w_default)
            return w_default
        else:
            self.switch_to_object_strategy(w_dict)
            return w_dict.setdefault(w_key, w_default)

    def delitem(self, w_dict, w_key):
        space = self.space
        w_key_type = space.type(w_key)
        w_obj = self.unerase(w_dict.dstorage)
        if space.is_w(w_key_type, space.w_str):
            key = self.space.str_w(w_key)
            flag = w_obj.deldictvalue(space, key)
            if not flag:
                raise KeyError
        elif _never_equal_to_string(space, w_key_type):
            raise KeyError
        else:
            self.switch_to_object_strategy(w_dict)
            w_dict.delitem(w_key)

    def length(self, w_dict):
        res = 0
        curr = self.unerase(w_dict.dstorage)._get_mapdict_map().search(DICT)
        while curr is not None:
            curr = curr.back
            curr = curr.search(DICT)
            res += 1
        return res

    def iter(self, w_dict):
        return MapDictIteratorImplementation(self.space, self, w_dict)

    def clear(self, w_dict):
        w_obj = self.unerase(w_dict.dstorage)
        new_obj = w_obj._get_mapdict_map().remove_dict_entries(w_obj)
        _become(w_obj, new_obj)

    def popitem(self, w_dict):
        curr = self.unerase(w_dict.dstorage)._get_mapdict_map().search(DICT)
        if curr is None:
            raise KeyError
        key = curr.selector[0]
        w_value = self.getitem_str(w_dict, key)
        w_key = self.space.wrap(key)
        self.delitem(w_dict, w_key)
        return (w_key, w_value)
Esempio n. 19
0
class EmptyListStrategy(ListStrategy):
    """EmptyListStrategy is used when a W_List withouth elements is created.
    The storage is None. When items are added to the W_List a new RPython list
    is created and the strategy and storage of the W_List are changed depending
    to the added item.
    W_Lists do not switch back to EmptyListStrategy when becoming empty again."""

    _applevel_repr = "empty"

    def __init__(self, space):
        ListStrategy.__init__(self, space)
        # cache an empty list that is used whenever getitems is called (i.e. sorting)
        self.cached_emptylist_w = []

    def init_from_list_w(self, w_list, list_w):
        assert len(list_w) == 0
        w_list.lstorage = self.erase(None)

    erase, unerase = rerased.new_erasing_pair("empty")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def clone(self, w_list):
        return W_ListObject.from_storage_and_strategy(self.space,
                                                      w_list.lstorage, self)

    def copy_into(self, w_list, w_other):
        pass

    def contains(self, w_list, w_obj):
        return False

    def length(self, w_list):
        return 0

    def getitem(self, w_list, index):
        raise IndexError

    def getslice(self, w_list, start, stop, step, length):
        # will never be called because the empty list case is already caught in
        # getslice__List_ANY_ANY and getitem__List_Slice
        return W_ListObject(self.space, self.cached_emptylist_w)

    def getitems(self, w_list):
        return self.cached_emptylist_w

    def getitems_copy(self, w_list):
        return []

    getitems_fixedsize = func_with_new_name(getitems_copy,
                                            "getitems_fixedsize")
    getitems_unroll = getitems_fixedsize

    def getstorage_copy(self, w_list):
        return self.erase(None)

    def switch_to_correct_strategy(self, w_list, w_item):
        if is_W_IntObject(w_item):
            strategy = self.space.fromcache(IntegerListStrategy)
        elif is_W_StringObject(w_item):
            strategy = self.space.fromcache(StringListStrategy)
        elif is_W_FloatObject(w_item):
            strategy = self.space.fromcache(FloatListStrategy)
        else:
            strategy = self.space.fromcache(ObjectListStrategy)

        storage = strategy.get_empty_storage()
        w_list.strategy = strategy
        w_list.lstorage = storage

    def append(self, w_list, w_item):
        self.switch_to_correct_strategy(w_list, w_item)
        w_list.append(w_item)

    def inplace_mul(self, w_list, times):
        return

    def deleteslice(self, w_list, start, step, slicelength):
        pass

    def pop(self, w_list, index):
        # will not be called because IndexError was already raised in
        # list_pop__List_ANY
        raise IndexError

    def setitem(self, w_list, index, w_item):
        raise IndexError

    def setslice(self, w_list, start, step, slicelength, w_other):
        strategy = w_other.strategy
        storage = strategy.getstorage_copy(w_other)
        w_list.strategy = strategy
        w_list.lstorage = storage

    def sort(self, w_list, reverse):
        return

    def insert(self, w_list, index, w_item):
        assert index == 0
        self.append(w_list, w_item)

    def extend(self, w_list, w_other):
        w_other.copy_into(w_list)

    def reverse(self, w_list):
        pass
Esempio n. 20
0
class EmptyDictStrategy(DictStrategy):

    erase, unerase = rerased.new_erasing_pair("empty")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def get_empty_storage(self):
       return self.erase(None)

    def switch_to_correct_strategy(self, w_dict, w_key):
        withidentitydict = self.space.config.objspace.std.withidentitydict
        if type(w_key) is self.space.StringObjectCls:
            self.switch_to_string_strategy(w_dict)
            return
        w_type = self.space.type(w_key)
        if self.space.is_w(w_type, self.space.w_int):
            self.switch_to_int_strategy(w_dict)
        elif withidentitydict and w_type.compares_by_identity():
            self.switch_to_identity_strategy(w_dict)
        else:
            self.switch_to_object_strategy(w_dict)

    def switch_to_string_strategy(self, w_dict):
        strategy = self.space.fromcache(StringDictStrategy)
        storage = strategy.get_empty_storage()
        w_dict.strategy = strategy
        w_dict.dstorage = storage

    def switch_to_int_strategy(self, w_dict):
        strategy = self.space.fromcache(IntDictStrategy)
        storage = strategy.get_empty_storage()
        w_dict.strategy = strategy
        w_dict.dstorage = storage

    def switch_to_identity_strategy(self, w_dict):
        from pypy.objspace.std.identitydict import IdentityDictStrategy
        strategy = self.space.fromcache(IdentityDictStrategy)
        storage = strategy.get_empty_storage()
        w_dict.strategy = strategy
        w_dict.dstorage = storage

    def switch_to_object_strategy(self, w_dict):
        strategy = self.space.fromcache(ObjectDictStrategy)
        storage = strategy.get_empty_storage()
        w_dict.strategy = strategy
        w_dict.dstorage = storage

    def getitem(self, w_dict, w_key):
        #return w_value or None
        # in case the key is unhashable, try to hash it
        self.space.hash(w_key)
        # return None anyway
        return None

    def getitem_str(self, w_dict, key):
        #return w_value or None
        return None

    def setdefault(self, w_dict, w_key, w_default):
        # here the dict is always empty
        self.switch_to_correct_strategy(w_dict, w_key)
        w_dict.setitem(w_key, w_default)
        return w_default

    def setitem(self, w_dict, w_key, w_value):
        self.switch_to_correct_strategy(w_dict, w_key)
        w_dict.setitem(w_key, w_value)

    def setitem_str(self, w_dict, key, w_value):
        self.switch_to_string_strategy(w_dict)
        w_dict.setitem_str(key, w_value)

    def delitem(self, w_dict, w_key):
        # in case the key is unhashable, try to hash it
        self.space.hash(w_key)
        raise KeyError

    def length(self, w_dict):
        return 0

    def iter(self, w_dict):
        return EmptyIteratorImplementation(self.space, self, w_dict)

    def clear(self, w_dict):
        return

    def popitem(self, w_dict):
        raise KeyError

    def view_as_kwargs(self, w_dict):
        return ([], [])
Esempio n. 21
0
class IdentityDictStrategy(AbstractTypedStrategy, DictStrategy):
    """
    Strategy for custom instances which compares by identity (i.e., the
    default unless you override __hash__, __eq__ or __cmp__).  The storage is
    just a normal RPython dict, which has already the correct by-identity
    semantics.

    Note that at a first sight, you might have problems if you mutate the
    class of an object which is already inside an identitydict.  Consider this
    example::

    class X(object):
        pass
    d = {x(): 1}
    X.__eq__ = ...
    d[y] # might trigger a call to __eq__?

    We want to be sure that x.__eq__ is called in the same cases as in
    CPython.  However, as long as the strategy is IdentityDictStrategy, the
    __eq__ will never be called.

    It turns out that it's not a problem.  In CPython (and in PyPy without
    this strategy), the __eq__ is called if ``hash(y) == hash(x)`` and ``x is
    not y``.  Note that hash(x) is computed at the time when we insert x in
    the dict, not at the time we lookup y.

    Now, how can hash(y) == hash(x)?  There are two possibilities:

      1. we write a custom __hash__ for the class of y, thus making it a not
        "compares by reference" type

      2. the class of y is "compares by reference" type, and by chance the
         hash is the same as x

    In the first case, the getitem immediately notice that y is not of the
    right type, and switches the strategy to ObjectDictStrategy, then the
    lookup works as usual.

    The second case is completely non-deterministic, even in CPython.
    Depending on the phase of the moon, you might call the __eq__ or not, so
    it is perfectly fine to *never* call it.  Morever, in practice with the
    minimark GC we never have two live objects with the same hash, so it would
    never happen anyway.
    """

    erase, unerase = rerased.new_erasing_pair("identitydict")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    def wrap(self, unwrapped):
        return unwrapped

    def unwrap(self, wrapped):
        return wrapped

    def get_empty_storage(self):
        d = {}
        mark_dict_non_null(d)
        return self.erase(d)

    def is_correct_type(self, w_obj):
        w_type = self.space.type(w_obj)
        return w_type.compares_by_identity()

    def _never_equal_to(self, w_lookup_type):
        return False

    def iter(self, w_dict):
        return IdentityDictIteratorImplementation(self.space, self, w_dict)

    def w_keys(self, w_dict):
        return self.space.newlist(self.unerase(w_dict.dstorage).keys())
Esempio n. 22
0
        return _subclass_cache[key]
    except KeyError:
        assert not hasattr(supercls, "__del__")
        result = []
        for i in range(SUBCLASSES_MIN_FIELDS, SUBCLASSES_MAX_FIELDS+1):
            result.append(_make_subclass_size_n(supercls, i))
        for i in range(SUBCLASSES_MIN_FIELDS):
            result.insert(0, result[0])
        if SUBCLASSES_MIN_FIELDS == SUBCLASSES_MAX_FIELDS:
            assert len(set(result)) == 1
        _subclass_cache[key] = result
        return result
memo_get_subclass_of_correct_size._annspecialcase_ = "specialize:memo"
_subclass_cache = {}

erase_item, unerase_item = rerased.new_erasing_pair("mapdict storage item")
erase_list, unerase_list = rerased.new_erasing_pair("mapdict storage list")

def _make_subclass_size_n(supercls, n):
    from pypy.rlib import unroll
    rangen = unroll.unrolling_iterable(range(n))
    nmin1 = n - 1
    rangenmin1 = unroll.unrolling_iterable(range(nmin1))
    class subcls(BaseMapdictObject, supercls):
        def _init_empty(self, map):
            from pypy.rlib.debug import make_sure_not_resized
            for i in rangen:
                setattr(self, "_value%s" % i, erase_item(None))
            self.map = map

        def _has_storage_list(self):
Esempio n. 23
0
class ModuleDictStrategy(DictStrategy):

    erase, unerase = rerased.new_erasing_pair("modulecell")
    erase = staticmethod(erase)
    unerase = staticmethod(unerase)

    _immutable_fields_ = ["version?"]

    def __init__(self, space):
        self.space = space
        self.version = VersionTag()

    def get_empty_storage(self):
        return self.erase({})

    def mutated(self):
        self.version = VersionTag()

    def getdictvalue_no_unwrapping(self, w_dict, key):
        # NB: it's important to promote self here, so that self.version is a
        # no-op due to the quasi-immutable field
        self = jit.promote(self)
        return self._getdictvalue_no_unwrapping_pure(self.version, w_dict, key)

    @jit.elidable_promote('0,1,2')
    def _getdictvalue_no_unwrapping_pure(self, version, w_dict, key):
        return self.unerase(w_dict.dstorage).get(key, None)

    def setitem(self, w_dict, w_key, w_value):
        space = self.space
        if space.is_w(space.type(w_key), space.w_str):
            self.setitem_str(w_dict, self.space.str_w(w_key), w_value)
        else:
            self.switch_to_object_strategy(w_dict)
            w_dict.setitem(w_key, w_value)

    def setitem_str(self, w_dict, key, w_value):
        cell = self.getdictvalue_no_unwrapping(w_dict, key)
        if isinstance(cell, ModuleCell):
            cell.w_value = w_value
            return
        if cell is not None:
            # If the new value and the current value are the same, don't create a
            # level of indirection, or mutate the version.
            if self.space.is_w(w_value, cell):
                return
            w_value = ModuleCell(w_value)
        self.mutated()
        self.unerase(w_dict.dstorage)[key] = w_value

    def setdefault(self, w_dict, w_key, w_default):
        space = self.space
        if space.is_w(space.type(w_key), space.w_str):
            key = space.str_w(w_key)
            w_result = self.getitem_str(w_dict, key)
            if w_result is not None:
                return w_result
            self.setitem_str(w_dict, key, w_default)
            return w_default
        else:
            self.switch_to_object_strategy(w_dict)
            return w_dict.setdefault(w_key, w_default)

    def delitem(self, w_dict, w_key):
        space = self.space
        w_key_type = space.type(w_key)
        if space.is_w(w_key_type, space.w_str):
            key = space.str_w(w_key)
            dict_w = self.unerase(w_dict.dstorage)
            try:
                del dict_w[key]
            except KeyError:
                raise
            else:
                self.mutated()
        elif _never_equal_to_string(space, w_key_type):
            raise KeyError
        else:
            self.switch_to_object_strategy(w_dict)
            w_dict.delitem(w_key)

    def length(self, w_dict):
        return len(self.unerase(w_dict.dstorage))

    def getitem(self, w_dict, w_key):
        space = self.space
        w_lookup_type = space.type(w_key)
        if space.is_w(w_lookup_type, space.w_str):
            return self.getitem_str(w_dict, space.str_w(w_key))

        elif _never_equal_to_string(space, w_lookup_type):
            return None
        else:
            self.switch_to_object_strategy(w_dict)
            return w_dict.getitem(w_key)

    def getitem_str(self, w_dict, key):
        w_res = self.getdictvalue_no_unwrapping(w_dict, key)
        return unwrap_cell(w_res)

    def iter(self, w_dict):
        return ModuleDictIteratorImplementation(self.space, self, w_dict)

    def keys(self, w_dict):
        space = self.space
        iterator = self.unerase(w_dict.dstorage).iteritems
        return [space.wrap(key) for key, cell in iterator()]

    def values(self, w_dict):
        iterator = self.unerase(w_dict.dstorage).itervalues
        return [unwrap_cell(cell) for cell in iterator()]

    def items(self, w_dict):
        space = self.space
        iterator = self.unerase(w_dict.dstorage).iteritems
        return [
            space.newtuple([space.wrap(key),
                            unwrap_cell(cell)]) for key, cell in iterator()
        ]

    def clear(self, w_dict):
        iterator = self.unerase(w_dict.dstorage).clear()
        self.mutated()

    def popitem(self, w_dict):
        d = self.unerase(w_dict.dstorage)
        key, w_value = d.popitem()
        self.mutated()
        return self.space.wrap(key), unwrap_cell(w_value)

    def switch_to_object_strategy(self, w_dict):
        d = self.unerase(w_dict.dstorage)
        strategy = self.space.fromcache(ObjectDictStrategy)
        d_new = strategy.unerase(strategy.get_empty_storage())
        for key, cell in d.iteritems():
            d_new[self.space.wrap(key)] = unwrap_cell(cell)
        w_dict.strategy = strategy
        w_dict.dstorage = strategy.erase(d_new)
Esempio n. 24
0
        assert not hasattr(supercls, "__del__")
        result = []
        for i in range(SUBCLASSES_MIN_FIELDS, SUBCLASSES_MAX_FIELDS + 1):
            result.append(_make_subclass_size_n(supercls, i))
        for i in range(SUBCLASSES_MIN_FIELDS):
            result.insert(0, result[0])
        if SUBCLASSES_MIN_FIELDS == SUBCLASSES_MAX_FIELDS:
            assert len(set(result)) == 1
        _subclass_cache[key] = result
        return result


memo_get_subclass_of_correct_size._annspecialcase_ = "specialize:memo"
_subclass_cache = {}

erase_item, unerase_item = rerased.new_erasing_pair("mapdict storage item")
erase_list, unerase_list = rerased.new_erasing_pair("mapdict storage list")


def _make_subclass_size_n(supercls, n):
    from pypy.rlib import unroll
    rangen = unroll.unrolling_iterable(range(n))
    nmin1 = n - 1
    rangenmin1 = unroll.unrolling_iterable(range(nmin1))

    class subcls(BaseMapdictObject, supercls):
        def _init_empty(self, map):
            from pypy.rlib.debug import make_sure_not_resized
            for i in rangen:
                setattr(self, "_value%s" % i, erase_item(None))
            self.map = map