[pypy-svn] r34817 - in pypy/dist/pypy: jit/hintannotator jit/timeshifter jit/timeshifter/test rpython/lltypesystem
arigo at codespeak.net
arigo at codespeak.net
Tue Nov 21 00:11:11 CET 2006
Author: arigo
Date: Tue Nov 21 00:11:03 2006
New Revision: 34817
Added:
pypy/dist/pypy/jit/timeshifter/test/test_vdict.py (contents, props changed)
pypy/dist/pypy/jit/timeshifter/vdict.py (contents, props changed)
Modified:
pypy/dist/pypy/jit/hintannotator/model.py
pypy/dist/pypy/jit/timeshifter/oop.py
pypy/dist/pypy/jit/timeshifter/vlist.py
pypy/dist/pypy/rpython/lltypesystem/rdict.py
Log:
(pedronis, arigo)
Starting oopspec'ed dict support. As usual, kind of easy but a lot of
mess to get correctly typed while still avoiding total specialization
explosion.
Modified: pypy/dist/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/model.py (original)
+++ pypy/dist/pypy/jit/hintannotator/model.py Tue Nov 21 00:11:03 2006
@@ -576,6 +576,8 @@
operation_name, args = ll_func.oopspec.split('(', 1)
assert args.endswith(')')
args = args[:-1] + ',' # trailing comma to force tuple syntax
+ if args.strip() == ',':
+ args = '()'
argnames = ll_func.func_code.co_varnames[:len(args_hs)]
d = dict(zip(argnames, args_hs))
argtuple = eval(args, d)
Modified: pypy/dist/pypy/jit/timeshifter/oop.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/oop.py (original)
+++ pypy/dist/pypy/jit/timeshifter/oop.py Tue Nov 21 00:11:03 2006
@@ -22,6 +22,8 @@
operation_name, args = ll_func.oopspec.split('(', 1)
assert args.endswith(')')
args = args[:-1] + ',' # trailing comma to force tuple syntax
+ if args.strip() == ',':
+ args = '()'
argnames = ll_func.func_code.co_varnames[:nb_args]
d = dict(zip(argnames, [Index(n) for n in range(nb_args)]))
self.argtuple = eval(args, d)
@@ -55,6 +57,10 @@
typename, method = 'list', 'oop_newlist'
SELFTYPE = FUNCTYPE.RESULT.TO
self.is_method = False
+ elif operation_name == 'newdict':
+ typename, method = 'dict', 'oop_newdict'
+ SELFTYPE = FUNCTYPE.RESULT.TO
+ self.is_method = False
else:
typename, method = operation_name.split('.')
method = 'oop_%s_%s' % (typename, method)
Added: pypy/dist/pypy/jit/timeshifter/test/test_vdict.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/jit/timeshifter/test/test_vdict.py Tue Nov 21 00:11:03 2006
@@ -0,0 +1,19 @@
+from pypy.annotation.policy import AnnotatorPolicy
+from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests
+
+P_OOPSPEC = AnnotatorPolicy()
+P_OOPSPEC.novirtualcontainer = True
+P_OOPSPEC.oopspec = True
+
+
+class TestVDict(TimeshiftingTests):
+
+ def test_vdict(self):
+ def ll_function():
+ dic = {}
+ dic[12] = 34
+ dic[13] = 35
+ return dic[12]
+ res = self.timeshift(ll_function, [], [], policy=P_OOPSPEC)
+ assert res == 34
+ self.check_insns({})
Added: pypy/dist/pypy/jit/timeshifter/vdict.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/jit/timeshifter/vdict.py Tue Nov 21 00:11:03 2006
@@ -0,0 +1,253 @@
+import operator
+from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import rdict
+from pypy.jit.timeshifter.rcontainer import AbstractContainer, cachedtype
+from pypy.jit.timeshifter import rvalue
+from pypy.rlib.objectmodel import r_dict
+
+HASH = lltype.Signed
+
+
+class LLEqDesc(object):
+ __metaclass__ = cachedtype
+
+ def __init__(self, KEY, keyeq, keyhash):
+ # this makes one version of the following function per KEY,
+ # which is supposed to be the ll type of x and y
+
+ def lleq(x, y):
+ return keyeq(x, y)
+ def llhash(x):
+ return keyhash(x)
+
+ class VirtualDict(AbstractVirtualDict):
+
+ def make_item_boxes(self):
+ self.item_boxes = r_dict(lleq, llhash)
+
+ def getboxes(self):
+ return self.item_boxes.values()
+
+ def getitems_and_makeempty(self, rgenop):
+ result = [(rgenop.genconst(key), box, llhash(key))
+ for key, box in self.item_boxes.iteritems()]
+ self.item_boxes = None
+ return result
+
+ def getitem(self, keybox):
+ key = rvalue.ll_getvalue(keybox, KEY)
+ return self.item_boxes[key]
+
+ def setitem(self, keybox, valuebox):
+ key = rvalue.ll_getvalue(keybox, KEY)
+ self.item_boxes[key] = valuebox
+
+ def copy_from(self, other, memo):
+ assert isinstance(other, VirtualDict)
+ self.make_item_boxes()
+ for key, valuebox in other.item_boxes.iteritems():
+ self.item_boxes[key] = valuebox.copy(memo)
+
+ def replace(self, memo):
+ changes = []
+ for key, valuebox in self.item_boxes.iteritems():
+ newbox = valuebox.replace(memo)
+ if newbox is not valuebox:
+ changes.append((key, newbox))
+ for key, newbox in changes:
+ self.item_boxes[key] = newbox
+
+
+ class FrozenVirtualDict(AbstractFrozenVirtualDict):
+
+ def freeze_from(self, vdict, memo):
+ assert isinstance(vdict, VirtualDict)
+ frozens = []
+ for key, valuebox in vdict.item_boxes.iteritems():
+ frozens.append((key, valuebox.freeze(memo)))
+ self.fz_item_boxes = frozens
+
+ def same_keys_as(self, vdict, boxes):
+ assert isinstance(vdict, VirtualDict)
+ self_boxes = self.fz_item_boxes
+ vdict_boxes = vdict.item_boxes
+ if len(self_boxes) != len(vdict_boxes):
+ return False
+ for key, selfbox in self_boxes:
+ try:
+ vdictbox = vdict_boxes[key]
+ except KeyError:
+ return False
+ boxes.append((selfbox, vdictbox))
+ return True
+
+
+ self.VirtualDict = VirtualDict
+ self.FrozenVirtualDict = FrozenVirtualDict
+
+ VirtualDict.FrozenVirtualDict = FrozenVirtualDict
+
+
+class DictTypeDesc(object):
+ __metaclass__ = cachedtype
+
+ def __init__(self, hrtyper, DICT):
+ RGenOp = hrtyper.RGenOp
+ rtyper = hrtyper.rtyper
+ bk = rtyper.annotator.bookkeeper
+ self.DICT = DICT
+ self.DICTPTR = lltype.Ptr(DICT)
+ self.ptrkind = RGenOp.kindToken(self.DICTPTR)
+
+ argtypes = [bk.immutablevalue(DICT)]
+ ll_newdict_ptr = rtyper.annotate_helper_fn(rdict.ll_newdict,
+ argtypes)
+ self.gv_ll_newdict = RGenOp.constPrebuiltGlobal(ll_newdict_ptr)
+ self.tok_ll_newdict = RGenOp.sigToken(lltype.typeOf(ll_newdict_ptr).TO)
+
+ argtypes = [self.DICTPTR, DICT.KEY, DICT.VALUE, HASH]
+ ll_insertclean = rtyper.annotate_helper_fn(rdict.ll_dict_insertclean,
+ argtypes)
+ self.gv_ll_insertclean = RGenOp.constPrebuiltGlobal(ll_insertclean)
+ self.tok_ll_insertclean = RGenOp.sigToken(
+ lltype.typeOf(ll_insertclean).TO)
+
+ # XXX some fishing that only works if the DICT does not come from
+ # an r_dict
+ if DICT.keyeq is None:
+ keyeq = operator.eq
+ else:
+ assert isinstance(DICT.keyeq, lltype.staticAdtMethod)
+ keyeq = DICT.keyeq.__get__(42)
+ assert isinstance(DICT.keyhash, lltype.staticAdtMethod)
+ keyhash = DICT.keyhash.__get__(42)
+ keydesc = LLEqDesc(DICT.KEY, keyeq, keyhash)
+ self.VirtualDict = keydesc.VirtualDict
+
+ def _freeze_(self):
+ return True
+
+ def factory(self):
+ vdict = self.VirtualDict(self)
+ box = rvalue.PtrRedBox(self.ptrkind)
+ box.content = vdict
+ vdict.ownbox = box
+ return box
+
+TypeDesc = DictTypeDesc
+
+
+class AbstractFrozenVirtualDict(AbstractContainer):
+ __slots__ = ('typedesc',)
+
+ def __init__(self, typedesc):
+ self.typedesc = typedesc
+ #self.fz_item_boxes initialized later
+
+ def exactmatch(self, vdict, outgoingvarboxes, memo):
+ assert isinstance(vdict, AbstractVirtualDict)
+ contmemo = memo.containers
+ if self in contmemo:
+ ok = vdict is contmemo[self]
+ if not ok:
+ outgoingvarboxes.append(vdict.ownbox)
+ return ok
+ if vdict in contmemo:
+ assert contmemo[vdict] is not self
+ outgoingvarboxes.append(vdict.ownbox)
+ return False
+ assert self.typedesc is vdict.typedesc
+ boxes = []
+ if not self.same_keys_as(vdict, boxes):
+ outgoingvarboxes.append(vdict.ownbox)
+ return False
+ contmemo[self] = vdict
+ contmemo[vdict] = self
+ fullmatch = True
+ for selfbox, vdictbox in boxes:
+ if not selfbox.exactmatch(vdictbox,
+ outgoingvarboxes,
+ memo):
+ fullmatch = False
+ return fullmatch
+
+
+class AbstractVirtualDict(AbstractContainer):
+ __slots__ = ('typedesc', 'ownbox') # and no item_boxes
+
+ def __init__(self, typedesc):
+ self.typedesc = typedesc
+ self.make_item_boxes()
+ # self.ownbox = ... set in factory()
+
+ def enter_block(self, incoming, memo):
+ contmemo = memo.containers
+ if self not in contmemo:
+ contmemo[self] = None
+ for box in self.getboxes():
+ box.enter_block(incoming, memo)
+
+ def force_runtime_container(self, builder):
+ typedesc = self.typedesc
+ items = self.getitems_and_makeempty(builder.rgenop)
+
+ args_gv = [None]
+ gv_dict = builder.genop_call(typedesc.tok_ll_newdict,
+ typedesc.gv_ll_newdict,
+ args_gv)
+ self.ownbox.genvar = gv_dict
+ self.ownbox.content = None
+ for gv_key, valuebox, hash in items:
+ gv_hash = builder.rgenop.genconst(hash)
+ gv_value = valuebox.getgenvar(builder)
+ args_gv = [gv_dict, gv_key, gv_value, gv_hash]
+ builder.genop_call(typedesc.tok_ll_insertclean,
+ typedesc.gv_ll_insertclean,
+ args_gv)
+
+ def freeze(self, memo):
+ contmemo = memo.containers
+ try:
+ return contmemo[self]
+ except KeyError:
+ result = contmemo[self] = self.FrozenVirtualDict(self.typedesc)
+ result.freeze_from(self, memo)
+ return result
+
+ def copy(self, memo):
+ contmemo = memo.containers
+ try:
+ return contmemo[self]
+ except KeyError:
+ result = contmemo[self] = self.__class__(self.typedesc)
+ result.copy_from(self, memo)
+ result.ownbox = self.ownbox.copy(memo)
+ return result
+
+ def replace(self, memo):
+ contmemo = memo.containers
+ if self not in contmemo:
+ contmemo[self] = None
+ self.replace(memo)
+ self.ownbox = self.ownbox.replace(memo)
+
+
+def oop_newdict(jitstate, oopspecdesc):
+ return oopspecdesc.typedesc.factory()
+
+def oop_dict_setitem(jitstate, oopspecdesc, selfbox, keybox, valuebox):
+ content = selfbox.content
+ if isinstance(content, AbstractVirtualDict) and keybox.is_constant():
+ content.setitem(keybox, valuebox)
+ else:
+ oopspecdesc.residual_call(jitstate, [selfbox, keybox, valuebox])
+
+def oop_dict_getitem(jitstate, oopspecdesc, selfbox, keybox):
+ content = selfbox.content
+ if isinstance(content, AbstractVirtualDict) and keybox.is_constant():
+ try:
+ return content.getitem(keybox)
+ except KeyError:
+ return oopspecdesc.residual_exception(jitstate, KeyError)
+ else:
+ return oopspecdesc.residual_call(jitstate, [selfbox, keybox])
Modified: pypy/dist/pypy/jit/timeshifter/vlist.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/vlist.py (original)
+++ pypy/dist/pypy/jit/timeshifter/vlist.py Tue Nov 21 00:11:03 2006
@@ -26,6 +26,9 @@
self.tok_ll_setitem_fast = RGenOp.sigToken(
lltype.typeOf(ll_setitem_fast).TO)
+ def _freeze_(self):
+ return True
+
def factory(self, length, itembox):
vlist = VirtualList(self, length, itembox)
box = rvalue.PtrRedBox(self.ptrkind)
Modified: pypy/dist/pypy/rpython/lltypesystem/rdict.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rdict.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rdict.py Tue Nov 21 00:11:03 2006
@@ -170,6 +170,8 @@
'keyeq': ll_keyeq,
'paranoia': False,
}
+ adtmeths['KEY'] = self.DICTKEY
+ adtmeths['VALUE'] = self.DICTVALUE
self.DICT.become(lltype.GcStruct("dicttable", adtmeths=adtmeths,
*fields))
@@ -394,6 +396,7 @@
return entry.value
else:
raise KeyError
+ll_dict_getitem.oopspec = 'dict.getitem(d, key)'
def ll_dict_setitem(d, key, value):
hash = d.keyhash(key)
@@ -414,6 +417,7 @@
d.num_pristine_entries -= 1
if d.num_pristine_entries <= len(d.entries) / 3:
ll_dict_resize(d)
+ll_dict_setitem.oopspec = 'dict.setitem(d, key, value)'
def ll_dict_insertclean(d, key, value, hash):
# Internal routine used by ll_dict_resize() to insert an item which is
@@ -554,6 +558,7 @@
d.num_items = 0
d.num_pristine_entries = DICT_INITSIZE
return d
+ll_newdict.oopspec = 'newdict()'
def ll_newdict_size(DICT, length_estimate):
length_estimate = (length_estimate // 2) * 3
@@ -565,6 +570,7 @@
d.num_items = 0
d.num_pristine_entries = DICT_INITSIZE
return d
+ll_newdict_size.oopspec = 'newdict()'
def rtype_r_dict(hop):
More information about the Pypy-commit
mailing list