[pypy-svn] r64783 - in pypy/branch/pyjitpl5/pypy: jit/metainterp jit/metainterp/test rpython rpython/lltypesystem rpython/ootypesystem
arigo at codespeak.net
arigo at codespeak.net
Tue Apr 28 16:52:45 CEST 2009
Author: arigo
Date: Tue Apr 28 16:52:44 2009
New Revision: 64783
Modified:
pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py
pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dict.py
pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rdict.py
pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rdict.py
pypy/branch/pyjitpl5/pypy/rpython/rdict.py
Log:
Refactor oopspec's of dictionaries to support keys(),
values(), items(), iterkeys(), itervalues(), iteritems().
Really add a test, which shows that the previous solution
was just translating but not working correctly.
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/support.py Tue Apr 28 16:52:44 2009
@@ -132,6 +132,8 @@
_ll_2_list_getitem_foldable = _ll_2_list_getitem
_ll_1_list_len_foldable = _ll_1_list_len
+# ---------- dict ----------
+
def _ll_0_newdict(DICT):
return rdict.ll_newdict(DICT)
_ll_0_newdict.need_result_type = True
@@ -142,19 +144,37 @@
_ll_3_dict_setdefault = rdict.ll_setdefault
_ll_2_dict_contains = rdict.ll_contains
_ll_3_dict_get = rdict.ll_get
-def _ll_1_newdictiter(ITERPTR, d):
- return rdict.ll_dictiter(lltype.Ptr(ITERPTR), d)
-_ll_1_newdictiter.need_result_type = True
-def _ll_2_dictiter_dictnext(RESULTTYPE, dic, func):
- return rdict.ll_dictnext(dic, func, RESULTTYPE)
-_ll_2_dictiter_dictnext.need_result_type = True
-def _ll_2_newdictkvi(LIST, dic, func):
- return rdict.ll_kvi(dic, LIST, func)
-_ll_2_newdictkvi.need_result_type = True
_ll_1_dict_copy = rdict.ll_copy
_ll_1_dict_clear = rdict.ll_clear
_ll_2_dict_update = rdict.ll_update
+# ---------- dict keys(), values(), items(), iter ----------
+
+_ll_1_dict_keys = rdict.ll_dict_keys
+_ll_1_dict_values = rdict.ll_dict_values
+_ll_1_dict_items = rdict.ll_dict_items
+_ll_1_dict_keys .need_result_type = True
+_ll_1_dict_values.need_result_type = True
+_ll_1_dict_items .need_result_type = True
+
+def _ll_1_newdictiter(ITER, d):
+ return rdict.ll_dictiter(lltype.Ptr(ITER), d)
+_ll_1_newdictiter.need_result_type = True
+
+_dictnext_keys = rdict.ll_dictnext_group['keys']
+_dictnext_values = rdict.ll_dictnext_group['values']
+_dictnext_items = rdict.ll_dictnext_group['items']
+
+def _ll_1_dictiter_nextkeys(iter):
+ return _dictnext_keys(None, iter)
+def _ll_1_dictiter_nextvalues(iter):
+ return _dictnext_values(None, iter)
+def _ll_1_dictiter_nextitems(RES, iter):
+ return _dictnext_items(lltype.Ptr(RES), iter)
+_ll_1_dictiter_nextitems.need_result_type = True
+
+# ---------- strings and unicode ----------
+
_ll_5_string_copy_contents = rstr.copy_string_contents
_ll_1_str_str2unicode = rstr.LLHelpers.ll_str2unicode
Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dict.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dict.py (original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_dict.py Tue Apr 28 16:52:44 2009
@@ -4,27 +4,60 @@
class DictTests:
- def test_basic_dict(self):
- py.test.skip("in-progress")
- myjitdriver = JitDriver(greens = [], reds = ['n', 'dct'])
+ def test_dict_keys_values_items(self):
+ for name, extract, expected in [('keys', None, 'k'),
+ ('values', None, 'v'),
+ ('items', 0, 'k'),
+ ('items', 1, 'v'),
+ ]:
+ myjitdriver = JitDriver(greens = [], reds = ['n', 'dct'])
+ def f(n):
+ dct = {}
+ while n > 0:
+ myjitdriver.can_enter_jit(n=n, dct=dct)
+ myjitdriver.jit_merge_point(n=n, dct=dct)
+ dct[n] = n*n
+ n -= 1
+ sum = 0
+ for x in getattr(dct, name)():
+ if extract is not None:
+ x = x[extract]
+ sum += x
+ return sum
+
+ if expected == 'k':
+ expected = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10
+ else:
+ expected = 1 + 4 + 9 + 16 + 25 + 36 + 49 + 64 + 81 + 100
+
+ assert f(10) == expected
+ res = self.meta_interp(f, [10], listops=True)
+ assert res == expected
+
+ def test_dict_iter(self):
+ myjitdriver = JitDriver(greens = [], reds = ['total', 'it'])
def f(n):
- dct = {}
- while n > 0:
- myjitdriver.can_enter_jit(n=n, dct=dct)
- myjitdriver.jit_merge_point(n=n, dct=dct)
- dct[n] = n*n
- n -= 1
- sum = 0
- for i in dct.values():
- sum += i
- return sum
- assert f(10) == 1 + 4 + 9 + 16 + 25 + 36 + 49 + 64 + 81 + 100
+ dct = {n: 100, 50: n+1}
+ it = dct.iterkeys()
+ total = 0
+ while True:
+ myjitdriver.can_enter_jit(total=total, it=it)
+ myjitdriver.jit_merge_point(total=total, it=it)
+ try:
+ total += it.next()
+ except StopIteration:
+ break
+ return total
+
+ assert f(10) == 60
res = self.meta_interp(f, [10], listops=True)
- assert res == 1 + 4 + 9 + 16 + 25 + 36 + 49 + 64 + 81 + 100
+ assert res == 60
class TestOOtype(DictTests, OOJitMixin):
- def test_basic_dict(self):
+ def test_dict_keys_values_items(self):
+ py.test.skip("implement me")
+ def test_dict_iter(self):
py.test.skip("implement me")
class TestLLtype(DictTests, LLJitMixin):
Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rdict.py (original)
+++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rdict.py Tue Apr 28 16:52:44 2009
@@ -2,7 +2,7 @@
from pypy.annotation import model as annmodel
from pypy.objspace.flow.model import Constant
from pypy.rpython.rdict import AbstractDictRepr, AbstractDictIteratorRepr,\
- rtype_newdict, dum_variant, dum_keys, dum_values, dum_items
+ rtype_newdict
from pypy.rpython.lltypesystem import lltype
from pypy.rlib.rarithmetic import r_uint, intmask
from pypy.rlib.objectmodel import hlinvoke
@@ -273,22 +273,21 @@
hop.exception_cannot_occur()
return hop.gendirectcall(ll_update, v_dic1, v_dic2)
- def _rtype_method_kvi(self, hop, spec):
+ def _rtype_method_kvi(self, hop, ll_func):
v_dic, = hop.inputargs(self)
r_list = hop.r_result
- v_func = hop.inputconst(lltype.Void, spec)
cLIST = hop.inputconst(lltype.Void, r_list.lowleveltype.TO)
hop.exception_cannot_occur()
- return hop.gendirectcall(ll_kvi, v_dic, cLIST, v_func)
+ return hop.gendirectcall(ll_func, cLIST, v_dic)
def rtype_method_keys(self, hop):
- return self._rtype_method_kvi(hop, dum_keys)
+ return self._rtype_method_kvi(hop, ll_dict_keys)
def rtype_method_values(self, hop):
- return self._rtype_method_kvi(hop, dum_values)
+ return self._rtype_method_kvi(hop, ll_dict_values)
def rtype_method_items(self, hop):
- return self._rtype_method_kvi(hop, dum_items)
+ return self._rtype_method_kvi(hop, ll_dict_items)
def rtype_method_iterkeys(self, hop):
hop.exception_cannot_occur()
@@ -422,7 +421,6 @@
else:
raise KeyError
ll_dict_getitem.oopspec = 'dict.getitem(d, key)'
-ll_dict_getitem.oopargcheck = lambda d, key: bool(d)
def ll_dict_setitem(d, key, value):
hash = d.keyhash(key)
@@ -651,7 +649,7 @@
('dict', r_dict.lowleveltype),
('index', lltype.Signed)))
self.ll_dictiter = ll_dictiter
- self.ll_dictnext = ll_dictnext
+ self.ll_dictnext = ll_dictnext_group[variant]
def ll_dictiter(ITERPTR, d):
@@ -661,33 +659,41 @@
return iter
ll_dictiter.oopspec = 'newdictiter(d)'
-def ll_dictnext(iter, func, RETURNTYPE):
- dict = iter.dict
- if dict:
- entries = dict.entries
- index = iter.index
- entries_len = len(entries)
- while index < entries_len:
- entry = entries[index]
- is_valid = entries.valid(index)
- index = index + 1
- if is_valid:
- iter.index = index
- if RETURNTYPE is lltype.Void:
- return None
- elif func is dum_items:
- r = lltype.malloc(RETURNTYPE.TO)
- r.item0 = recast(RETURNTYPE.TO.item0, entry.key)
- r.item1 = recast(RETURNTYPE.TO.item1, entry.value)
- return r
- elif func is dum_keys:
- return entry.key
- elif func is dum_values:
- return entry.value
- # clear the reference to the dict and prevent restarts
- iter.dict = lltype.nullptr(lltype.typeOf(iter).TO.dict.TO)
- raise StopIteration
-ll_dictnext.oopspec = 'dictiter.dictnext(iter, func)'
+def _make_ll_dictnext(kind):
+ # make three versions of the following function: keys, values, items
+ def ll_dictnext(RETURNTYPE, iter):
+ # note that RETURNTYPE is None for keys and values
+ dict = iter.dict
+ if dict:
+ entries = dict.entries
+ index = iter.index
+ entries_len = len(entries)
+ while index < entries_len:
+ entry = entries[index]
+ is_valid = entries.valid(index)
+ index = index + 1
+ if is_valid:
+ iter.index = index
+ if RETURNTYPE is lltype.Void:
+ return None
+ elif kind == 'items':
+ r = lltype.malloc(RETURNTYPE.TO)
+ r.item0 = recast(RETURNTYPE.TO.item0, entry.key)
+ r.item1 = recast(RETURNTYPE.TO.item1, entry.value)
+ return r
+ elif kind == 'keys':
+ return entry.key
+ elif kind == 'values':
+ return entry.value
+ # clear the reference to the dict and prevent restarts
+ iter.dict = lltype.nullptr(lltype.typeOf(iter).TO.dict.TO)
+ raise StopIteration
+ ll_dictnext.oopspec = 'dictiter.next%s(iter)' % kind
+ return ll_dictnext
+
+ll_dictnext_group = {'keys' : _make_ll_dictnext('keys'),
+ 'values': _make_ll_dictnext('values'),
+ 'items' : _make_ll_dictnext('items')}
# _____________________________________________________________
# methods
@@ -766,35 +772,40 @@
else:
return v
-def ll_kvi(dic, LIST, func):
- res = LIST.ll_newlist(dic.num_items)
- entries = dic.entries
- dlen = len(entries)
- items = res.ll_items()
- i = 0
- p = 0
- while i < dlen:
- if entries.valid(i):
- ELEM = lltype.typeOf(items).TO.OF
- if ELEM is not lltype.Void:
- entry = entries[i]
- if func is dum_items:
- r = lltype.malloc(ELEM.TO)
- r.item0 = recast(ELEM.TO.item0, entry.key)
- r.item1 = recast(ELEM.TO.item1, entry.value)
- items[p] = r
- elif func is dum_keys:
- items[p] = recast(ELEM, entry.key)
- elif func is dum_values:
- items[p] = recast(ELEM, entry.value)
- p += 1
- i += 1
- assert p == res.ll_length()
- return res
-ll_kvi.oopspec = 'newdictkvi(dic, func)'
+def _make_ll_keys_values_items(kind):
+ def ll_kvi(LIST, dic):
+ res = LIST.ll_newlist(dic.num_items)
+ entries = dic.entries
+ dlen = len(entries)
+ items = res.ll_items()
+ i = 0
+ p = 0
+ while i < dlen:
+ if entries.valid(i):
+ ELEM = lltype.typeOf(items).TO.OF
+ if ELEM is not lltype.Void:
+ entry = entries[i]
+ if kind == 'items':
+ r = lltype.malloc(ELEM.TO)
+ r.item0 = recast(ELEM.TO.item0, entry.key)
+ r.item1 = recast(ELEM.TO.item1, entry.value)
+ items[p] = r
+ elif kind == 'keys':
+ items[p] = recast(ELEM, entry.key)
+ elif kind == 'values':
+ items[p] = recast(ELEM, entry.value)
+ p += 1
+ i += 1
+ assert p == res.ll_length()
+ return res
+ ll_kvi.oopspec = 'dict.%s(dic)' % kind
+ return ll_kvi
+
+ll_dict_keys = _make_ll_keys_values_items('keys')
+ll_dict_values = _make_ll_keys_values_items('values')
+ll_dict_items = _make_ll_keys_values_items('items')
def ll_contains(d, key):
i = ll_dict_lookup(d, key, d.keyhash(key))
return d.entries.valid(i)
ll_contains.oopspec = 'dict.contains(d, key)'
-ll_contains.oopargcheck = lambda d, key: bool(d)
Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rdict.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rdict.py (original)
+++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rdict.py Tue Apr 28 16:52:44 2009
@@ -3,7 +3,7 @@
from pypy.annotation import model as annmodel
from pypy.objspace.flow.model import Constant
from pypy.rpython.rdict import AbstractDictRepr, AbstractDictIteratorRepr,\
- rtype_newdict, dum_variant, dum_keys, dum_values, dum_items
+ rtype_newdict
from pypy.rpython.rpbc import MethodOfFrozenPBCRepr,\
AbstractFunctionsPBCRepr, AbstractMethodsPBCRepr
from pypy.rpython.ootypesystem import ootype
@@ -121,21 +121,20 @@
return hop.gendirectcall(ll_dict_update, v_dict1, v_dict2)
def rtype_method_keys(self, hop):
- return self._rtype_method_kvi(hop, dum_keys)
+ return self._rtype_method_kvi(hop, ll_dict_keys)
def rtype_method_values(self, hop):
- return self._rtype_method_kvi(hop, dum_values)
+ return self._rtype_method_kvi(hop, ll_dict_values)
def rtype_method_items(self, hop):
- return self._rtype_method_kvi(hop, dum_items)
+ return self._rtype_method_kvi(hop, ll_dict_items)
- def _rtype_method_kvi(self, hop, spec):
+ def _rtype_method_kvi(self, hop, ll_func):
v_dict, = hop.inputargs(self)
r_list = hop.r_result
cLIST = hop.inputconst(ootype.Void, r_list.lowleveltype)
- c_func = hop.inputconst(ootype.Void, spec)
hop.exception_cannot_occur()
- return hop.gendirectcall(ll_dict_kvi, v_dict, cLIST, c_func)
+ return hop.gendirectcall(ll_func, cLIST, v_dict)
def rtype_method_iterkeys(self, hop):
hop.exception_cannot_occur()
@@ -321,25 +320,31 @@
d.ll_set(key, default)
return default
-def ll_dict_kvi(d, LIST, func):
- length = d.ll_length()
- result = LIST.ll_newlist(length)
- it = d.ll_get_items_iterator()
- i = 0
- while it.ll_go_next():
- if func is dum_keys:
- result.ll_setitem_fast(i, it.ll_current_key())
- elif func is dum_values:
- result.ll_setitem_fast(i, it.ll_current_value())
- if func is dum_items:
- r = ootype.new(LIST.ITEM)
- r.item0 = it.ll_current_key() # TODO: do we need casting?
- r.item1 = it.ll_current_value()
- result.ll_setitem_fast(i, r)
- i += 1
- assert i == length
- return result
-
+def _make_ll_keys_values_items(kind):
+ def ll_dict_kvi(LIST, d):
+ length = d.ll_length()
+ result = LIST.ll_newlist(length)
+ it = d.ll_get_items_iterator()
+ i = 0
+ while it.ll_go_next():
+ if kind == 'keys':
+ result.ll_setitem_fast(i, it.ll_current_key())
+ elif kind == 'values':
+ result.ll_setitem_fast(i, it.ll_current_value())
+ elif kind == 'items':
+ r = ootype.new(LIST.ITEM)
+ r.item0 = it.ll_current_key() # TODO: do we need casting?
+ r.item1 = it.ll_current_value()
+ result.ll_setitem_fast(i, r)
+ i += 1
+ assert i == length
+ return result
+ ll_dict_kvi.oopspec = 'dict.%s(d)' % kind
+ return ll_dict_kvi
+
+ll_dict_keys = _make_ll_keys_values_items('keys')
+ll_dict_values = _make_ll_keys_values_items('values')
+ll_dict_items = _make_ll_keys_values_items('items')
# ____________________________________________________________
#
@@ -352,7 +357,7 @@
self.variant = variant
self.lowleveltype = self._get_type()
self.ll_dictiter = ll_dictiter
- self.ll_dictnext = ll_dictnext
+ self.ll_dictnext = ll_dictnext_group[variant]
def _get_type(self):
KEYTYPE = self.r_dict.key_repr.lowleveltype
@@ -365,18 +370,26 @@
iter.iterator = d.ll_get_items_iterator()
return iter
-def ll_dictnext(iter, func, RETURNTYPE):
- it = iter.iterator
- if not it.ll_go_next():
- raise StopIteration
-
- if func is dum_keys:
- return it.ll_current_key()
- elif func is dum_values:
- return it.ll_current_value()
- elif func is dum_items:
- res = ootype.new(RETURNTYPE)
- res.item0 = it.ll_current_key()
- res.item1 = it.ll_current_value()
- return res
-
+def _make_ll_dictnext(kind):
+ # make three versions of the following function: keys, values, items
+ def ll_dictnext(RETURNTYPE, iter):
+ # note that RETURNTYPE is None for keys and values
+ it = iter.iterator
+ if not it.ll_go_next():
+ raise StopIteration
+
+ if kind == 'keys':
+ return it.ll_current_key()
+ elif kind == 'values':
+ return it.ll_current_value()
+ elif kind == 'items':
+ res = ootype.new(RETURNTYPE)
+ res.item0 = it.ll_current_key()
+ res.item1 = it.ll_current_value()
+ return res
+ ll_dictnext.oopspec = 'dictiter.next%s(iter)' % kind
+ return ll_dictnext
+
+ll_dictnext_group = {'keys' : _make_ll_dictnext('keys'),
+ 'values': _make_ll_dictnext('values'),
+ 'items' : _make_ll_dictnext('items')}
Modified: pypy/branch/pyjitpl5/pypy/rpython/rdict.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/rpython/rdict.py (original)
+++ pypy/branch/pyjitpl5/pypy/rpython/rdict.py Tue Apr 28 16:52:44 2009
@@ -8,13 +8,6 @@
from pypy.rlib import objectmodel
from pypy.rpython import rmodel
-def dum_keys(): pass
-def dum_values(): pass
-def dum_items():pass
-dum_variant = {"keys": dum_keys,
- "values": dum_values,
- "items": dum_items}
-
class __extend__(annmodel.SomeDict):
def rtyper_makerepr(self, rtyper):
@@ -92,7 +85,6 @@
def rtype_next(self, hop):
variant = self.variant
v_iter, = hop.inputargs(self)
- v_func = hop.inputconst(lltype.Void, dum_variant[self.variant])
if variant in ('keys', 'values'):
c1 = hop.inputconst(lltype.Void, None)
else:
@@ -101,7 +93,7 @@
hop.has_implicit_exception(StopIteration)
hop.has_implicit_exception(RuntimeError)
hop.exception_is_here()
- v = hop.gendirectcall(self.ll_dictnext, v_iter, v_func, c1)
+ v = hop.gendirectcall(self.ll_dictnext, c1, v_iter)
if variant == 'keys':
return self.r_dict.recast_key(hop.llops, v)
elif variant == 'values':
More information about the Pypy-commit
mailing list