[pypy-svn] r37823 - in pypy/branch/jit-virtual-world/pypy: jit/timeshifter jit/timeshifter/test rpython/lltypesystem
arigo at codespeak.net
arigo at codespeak.net
Fri Feb 2 20:59:07 CET 2007
Author: arigo
Date: Fri Feb 2 20:59:02 2007
New Revision: 37823
Modified:
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rcontainer.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rtimeshift.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rvalue.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_exception.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_promotion.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/vdict.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/vlist.py
pypy/branch/jit-virtual-world/pypy/rpython/lltypesystem/rclass.py
Log:
(arre, pedronis, arigo)
Add a flag 'known_nonzero' to PtrRedBox. This allows the propagation of
the fact that some pointers cannot be NULL, which is essential to get
reasonable code out of exception raising. This keeps exception-raising
paths separate from regular returns - otherwise the compiler would try
to produce code that uses normally the special "-1" value returned in
case of error!
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py Fri Feb 2 20:59:02 2007
@@ -1049,26 +1049,52 @@
[v_jitstate, var ],
self.s_ConstOrVar)
- def translate_op_split(self, hop):
+ def translate_op_split(self, hop, splitfn=rtimeshift.split,
+ reverse=False):
+ if splitfn is rtimeshift.split:
+ nb_fixed_args = 2
+ else:
+ nb_fixed_args = 3
+
r_switch = self.getredrepr(lltype.Bool)
- GREENS = [v.concretetype for v in hop.args_v[2:]]
- greens_r = [self.getgreenrepr(TYPE) for TYPE in GREENS]
- vlist = hop.inputargs(r_switch, lltype.Signed, *greens_r)
+ GREENS = [v.concretetype for v in hop.args_v[nb_fixed_args:]]
+ extra_r = [self.getgreenrepr(TYPE) for TYPE in GREENS]
+ if splitfn is not rtimeshift.split:
+ TYPE = originalconcretetype(hop.args_s[2])
+ r_ptrbox = self.getredrepr(TYPE)
+ extra_r.insert(0, r_ptrbox)
+ vlist = hop.inputargs(r_switch, lltype.Signed, *extra_r)
v_jitstate = hop.llops.getjitstate()
v_switch = vlist[0]
c_resumepoint = vlist[1]
- greens_v = list(self.wrap_green_vars(hop.llops, vlist[2:]))
+ greens_v = list(self.wrap_green_vars(hop.llops,
+ vlist[nb_fixed_args:]))
s_Int = annmodel.SomeInteger(nonneg=True)
args_s = [self.s_JITState, self.s_RedBox, s_Int]
- args_s += [self.s_ConstOrVar] * len(greens_v)
args_v = [v_jitstate, v_switch, c_resumepoint]
+
+ if splitfn is not rtimeshift.split:
+ v_ptrbox = vlist[2]
+ c_reverse = hop.inputconst(lltype.Bool, reverse)
+ args_s += [self.s_PtrRedBox, annmodel.s_Bool]
+ args_v += [hop.llops.as_ptrredbox(v_ptrbox), c_reverse ]
+
+ args_s += [self.s_ConstOrVar] * len(greens_v)
args_v += greens_v
- return hop.llops.genmixlevelhelpercall(rtimeshift.split,
+ return hop.llops.genmixlevelhelpercall(splitfn,
args_s, args_v,
annmodel.SomeBool())
+ def translate_op_split_ptr_nonzero(self, hop):
+ return self.translate_op_split(hop, rtimeshift.split_ptr_nonzero,
+ reverse=False)
+
+ def translate_op_split_ptr_iszero(self, hop):
+ return self.translate_op_split(hop, rtimeshift.split_ptr_nonzero,
+ reverse=True)
+
def translate_op_collect_split(self, hop):
GREENS = [v.concretetype for v in hop.args_v[1:]]
greens_r = [self.getgreenrepr(TYPE) for TYPE in GREENS]
@@ -1590,8 +1616,7 @@
typedesc.redirected_fielddescs])
TYPE = self.original_concretetype
kind = self.hrtyper.RGenOp.kindToken(TYPE)
- boxcls = rvalue.ll_redboxcls(TYPE)
-
+
def make_arg_redbox(jitstate, inputargs_gv, i):
box = typedesc.factory()
jitstate.add_virtualizable(box)
@@ -1601,9 +1626,12 @@
gv_outside = inputargs_gv[i]
i += 1
for name, j in names:
- content_boxes[j].genvar = inputargs_gv[i]
+ content_boxes[j] = rvalue.PtrRedBox(content_boxes[j].kind,
+ inputargs_gv[i])
i += 1
- content_boxes[-1].genvar = gv_outside
+ content_boxes[-1] = rvalue.PtrRedBox(content_boxes[-1].kind,
+ gv_outside,
+ known_nonzero = True)
return box
self.make_arg_redbox = make_arg_redbox
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rcontainer.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rcontainer.py Fri Feb 2 20:59:02 2007
@@ -178,7 +178,7 @@
vstruct = self.VirtualStructCls(self)
vstruct.content_boxes = [desc.makedefaultbox()
for desc in self.fielddescs]
- box = rvalue.PtrRedBox(self.innermostdesc.ptrkind)
+ box = rvalue.PtrRedBox(self.innermostdesc.ptrkind, known_nonzero=True)
box.content = vstruct
vstruct.ownbox = box
return box
@@ -191,7 +191,8 @@
gv_size = sizebox.getgenvar(jitstate)
alloctoken = contdesc.varsizealloctoken
genvar = jitstate.curbuilder.genop_malloc_varsize(alloctoken, gv_size)
- return rvalue.PtrRedBox(contdesc.ptrkind, genvar)
+ # XXX MemoryError checking
+ return rvalue.PtrRedBox(contdesc.ptrkind, genvar, known_nonzero=True)
class VirtualizableStructTypeDesc(StructTypeDesc):
@@ -353,6 +354,7 @@
gv_default = None
canbevirtual = False
gcref = False
+ fieldnonnull = False
def __init__(self, hrtyper, PTRTYPE, RESTYPE):
RGenOp = hrtyper.RGenOp
@@ -361,6 +363,7 @@
if isinstance(RESTYPE, lltype.ContainerType):
T = RESTYPE
RESTYPE = lltype.Ptr(RESTYPE)
+ self.fieldnonnull = True
elif isinstance(RESTYPE, lltype.Ptr):
T = RESTYPE.TO
if hasattr(T, '_hints'):
@@ -373,6 +376,7 @@
self.canbevirtual = True
else:
T = None
+ self.fieldnonnull = PTRTYPE.TO._hints.get('shouldntbenull', False)
self.RESTYPE = RESTYPE
self.ptrkind = RGenOp.kindToken(PTRTYPE)
self.kind = RGenOp.kindToken(RESTYPE)
@@ -400,7 +404,11 @@
assert isinstance(content, VirtualizableStruct)
content.load_from(jitstate, gvar)
return structbox
- return self.redboxcls(self.kind, gvar)
+ box = self.redboxcls(self.kind, gvar)
+ if self.fieldnonnull:
+ assert isinstance(box, rvalue.PtrRedBox)
+ box.known_nonzero = True
+ return box
class NamedFieldDesc(FieldDesc):
@@ -518,7 +526,7 @@
def setforced(self, gv_forced):
self.content_boxes = None
- self.ownbox.genvar = gv_forced
+ self.ownbox.setgenvar_hint(gv_forced, known_nonzero=True)
self.ownbox.content = None
def force_runtime_container(self, jitstate):
@@ -532,7 +540,7 @@
break
else:
gv = typedesc.materialize(builder.rgenop, boxes)
- self.ownbox.genvar = gv
+ self.ownbox.setgenvar_hint(gv, known_nonzero=True)
self.ownbox.content = None
return
debug_print(lltype.Void, "FORCE CONTAINER: "+ typedesc.TYPE._name)
@@ -657,7 +665,10 @@
assert isinstance(typedesc, VirtualizableStructTypeDesc)
builder = jitstate.curbuilder
gv_outside = builder.genop_malloc_fixedsize(typedesc.alloctoken)
- self.content_boxes[-1].genvar = gv_outside
+ outsidebox = rvalue.PtrRedBox(self.content_boxes[-1].kind,
+ gv_outside,
+ known_nonzero = True)
+ self.content_boxes[-1] = outsidebox
jitstate.add_virtualizable(self.ownbox)
access_token = typedesc.access_desc.fieldtoken
gv_access_null = typedesc.access_desc.gv_default
@@ -677,8 +688,11 @@
def load_from(self, jitstate, gv_outside):
typedesc = self.typedesc
assert isinstance(typedesc, VirtualizableStructTypeDesc)
+ # XXX missing check for gv_outside being NULL
boxes = self.content_boxes
- boxes[-1].genvar = gv_outside
+ boxes[-1] = rvalue.PtrRedBox(boxes[-1].kind,
+ gv_outside,
+ known_nonzero=True)
builder = jitstate.curbuilder
builder.genop_call(typedesc.access_is_null_token,
typedesc.gv_access_is_null_ptr,
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rtimeshift.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rtimeshift.py Fri Feb 2 20:59:02 2007
@@ -99,7 +99,8 @@
gv_size = sizebox.getgenvar(jitstate)
alloctoken = contdesc.varsizealloctoken
genvar = jitstate.curbuilder.genop_malloc_varsize(alloctoken, gv_size)
- return rvalue.PtrRedBox(contdesc.ptrkind, genvar)
+ # XXX MemoryError handling
+ return rvalue.PtrRedBox(contdesc.ptrkind, genvar, known_nonzero=True)
def ll_gengetfield(jitstate, deepfrozen, fielddesc, argbox):
if (fielddesc.immutable or deepfrozen) and argbox.is_constant():
@@ -167,14 +168,14 @@
addr = rvalue.ll_getvalue(argbox, llmemory.Address)
return rvalue.ll_fromvalue(jitstate, bool(addr) ^ reverse)
builder = jitstate.curbuilder
- if argbox.content is None:
+ if argbox.known_nonzero:
+ gv_res = builder.rgenop.genconst(True ^ reverse)
+ else:
gv_addr = argbox.getgenvar(jitstate)
if reverse:
gv_res = builder.genop_ptr_iszero(argbox.kind, gv_addr)
else:
gv_res = builder.genop_ptr_nonzero(argbox.kind, gv_addr)
- else:
- gv_res = builder.rgenop.genconst(True ^ reverse)
return rvalue.IntRedBox(builder.rgenop.kindToken(lltype.Bool), gv_res)
def ll_genptreq(jitstate, argbox0, argbox1, reverse):
@@ -201,6 +202,7 @@
linkargs = []
kinds = []
for redbox in incoming:
+ assert not redbox.genvar.is_const
linkargs.append(redbox.genvar)
kinds.append(redbox.kind)
newblock = jitstate.curbuilder.enter_next_block(kinds, linkargs)
@@ -270,9 +272,10 @@
# redboxes from outgoingvarboxes, by making them variables.
# Then we make a new block based on this new state.
cleanup_partial_data(memo.partialdatamatch)
+ forget_nonzeroness = memo.forget_nonzeroness
replace_memo = rvalue.copy_memo()
for box in outgoingvarboxes:
- box.forcevar(jitstate, replace_memo)
+ box.forcevar(jitstate, replace_memo, box in forget_nonzeroness)
if replace_memo.boxes:
jitstate.replace(replace_memo)
start_new_block(states_dic, jitstate, key, global_resumer, index=i)
@@ -323,14 +326,49 @@
if exitgvar.is_const:
return exitgvar.revealconst(lltype.Bool)
else:
+ # XXX call another function with list(greens_gv) instead
+ resuming = jitstate.resuming
+ if resuming is not None and resuming.mergesleft == 0:
+ node = resuming.path.pop()
+ assert isinstance(node, PromotionPathSplit)
+ return node.answer
+ false_gv = jitstate.get_locals_gv() # alive gvs on the false path
+ later_builder = jitstate.curbuilder.jump_if_false(exitgvar, false_gv)
+ memo = rvalue.copy_memo()
+ jitstate2 = jitstate.split(later_builder, resumepoint,
+ list(greens_gv), memo)
+ if resuming is None:
+ node = jitstate.promotion_path
+ jitstate2.promotion_path = PromotionPathNo(node)
+ jitstate .promotion_path = PromotionPathYes(node)
+ return True
+
+def split_ptr_nonzero(jitstate, switchredbox, resumepoint,
+ ptrbox, reverse, *greens_gv):
+ exitgvar = switchredbox.getgenvar(jitstate)
+ if exitgvar.is_const:
+ return exitgvar.revealconst(lltype.Bool)
+ else:
+ # XXX call another function with list(greens_gv) instead
resuming = jitstate.resuming
if resuming is not None and resuming.mergesleft == 0:
node = resuming.path.pop()
assert isinstance(node, PromotionPathSplit)
+ ptrbox.learn_nonzeroness(jitstate,
+ nonzeroness = node.answer ^ reverse)
return node.answer
false_gv = jitstate.get_locals_gv() # alive gvs on the false path
later_builder = jitstate.curbuilder.jump_if_false(exitgvar, false_gv)
- jitstate2 = jitstate.split(later_builder, resumepoint, list(greens_gv))
+ memo = rvalue.copy_memo()
+ jitstate2 = jitstate.split(later_builder, resumepoint,
+ list(greens_gv), memo)
+ ptrbox.learn_nonzeroness(jitstate, nonzeroness = True ^ reverse)
+ try:
+ copybox = memo.boxes[ptrbox]
+ except KeyError:
+ pass
+ else:
+ copybox.learn_nonzeroness(jitstate2, nonzeroness = reverse)
if resuming is None:
node = jitstate.promotion_path
jitstate2.promotion_path = PromotionPathNo(node)
@@ -541,6 +579,7 @@
kinds = [box.kind for box in incoming]
builder, vars_gv = self.rgenop.replay(self.replayableblock, kinds)
for i in range(len(incoming)):
+ assert incoming[i].genvar is None
incoming[i].genvar = vars_gv[i]
jitstate.curbuilder = builder
jitstate.greens = self.greens_gv
@@ -682,15 +721,16 @@
if len(resuming.path) == 0:
incoming_gv = pm.incoming_gv
for i in range(len(incoming)):
+ assert not incoming[i].genvar.is_const
incoming[i].genvar = incoming_gv[i]
flexswitch = pm.flexswitch
- promotebox.genvar = promotenode.gv_value
+ promotebox.setgenvar(promotenode.gv_value)
jitstate.resuming = None
node = PromotionPathMergesToSee(promotenode, 0)
jitstate.promotion_path = node
else:
resuming.merges_to_see()
- promotebox.genvar = promotenode.gv_value
+ promotebox.setgenvar(promotenode.gv_value)
newbuilder = flexswitch.add_case(promotenode.gv_value)
jitstate.curbuilder = newbuilder
@@ -869,8 +909,7 @@
if virtualizable_box not in self.virtualizables:
self.virtualizables.append(virtualizable_box)
- def split(self, newbuilder, newresumepoint, newgreens):
- memo = rvalue.copy_memo()
+ def split(self, newbuilder, newresumepoint, newgreens, memo):
virtualizables = []
for virtualizable_box in self.virtualizables:
new_virtualizable_box = virtualizable_box.copy(memo)
@@ -1112,6 +1151,8 @@
resuming = jitstate.resuming
return_chain = merge_returning_jitstates(jitstate, dispatchqueue,
force_merge=is_portal)
+ if is_portal:
+ assert return_chain is None or return_chain.next is None
if resuming is not None:
resuming.leave_call(dispatchqueue)
jitstate = return_chain
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rvalue.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rvalue.py Fri Feb 2 20:59:02 2007
@@ -16,6 +16,7 @@
def exactmatch_memo(force_merge=False):
memo = Memo()
memo.partialdatamatch = {}
+ memo.forget_nonzeroness = {}
memo.force_merge=force_merge
return memo
@@ -50,22 +51,24 @@
def getgenvar(self, jitstate):
return self.genvar
+ def setgenvar(self, newgenvar):
+ assert not self.is_constant()
+ self.genvar = newgenvar
+
def enter_block(self, incoming, memo):
memo = memo.boxes
if not self.is_constant() and self not in memo:
incoming.append(self)
memo[self] = None
- def forcevar(self, jitstate, memo):
- builder = jitstate.curbuilder
+ def forcevar(self, jitstate, memo, forget_nonzeroness):
if self.is_constant():
# cannot mutate constant boxes in-place
+ builder = jitstate.curbuilder
box = self.copy(memo)
box.genvar = builder.genop_same_as(self.kind, self.genvar)
return box
else:
- # force virtual containers
- self.getgenvar(jitstate)
return self
def replace(self, memo):
@@ -74,15 +77,8 @@
def ll_redboxcls(TYPE):
- if isinstance(TYPE, lltype.Ptr):
- return PtrRedBox
- elif TYPE is lltype.Float:
- return DoubleRedBox
- else:
- assert isinstance(TYPE, lltype.Primitive)
- assert TYPE is not lltype.Void, "cannot make red boxes of voids"
- # XXX what about long longs?
- return IntRedBox
+ assert TYPE is not lltype.Void, "cannot make red boxes of voids"
+ return ll_redboxbuilder(TYPE)
def redboxbuilder_void(kind, gv_value):return None
def redboxbuilder_int(kind, gv_value): return IntRedBox(kind, gv_value)
@@ -181,6 +177,29 @@
class PtrRedBox(RedBox):
content = None # or an AbstractContainer
+ def __init__(self, kind, genvar=None, known_nonzero=False):
+ self.kind = kind
+ self.genvar = genvar # None or a genvar
+ if genvar is not None and genvar.is_const:
+ known_nonzero = bool(genvar.revealconst(llmemory.Address))
+ self.known_nonzero = known_nonzero
+
+ def setgenvar(self, newgenvar):
+ RedBox.setgenvar(self, newgenvar)
+ self.known_nonzero = (newgenvar.is_const and
+ bool(newgenvar.revealconst(llmemory.Address)))
+
+ def setgenvar_hint(self, newgenvar, known_nonzero):
+ RedBox.setgenvar(self, newgenvar)
+ self.known_nonzero = known_nonzero
+
+ def learn_nonzeroness(self, jitstate, nonzeroness):
+ if nonzeroness:
+ self.known_nonzero = True
+ else:
+ gv_null = jitstate.curbuilder.rgenop.genzeroconst(self.kind)
+ self.setgenvar_hint(gv_null, known_nonzero=False)
+
def __repr__(self):
if not self.genvar and self.content is not None:
return '<virtual %s>' % (self.content,)
@@ -188,6 +207,7 @@
return RedBox.__repr__(self)
def op_getfield(self, jitstate, fielddesc):
+ self.known_nonzero = True
if self.content is not None:
box = self.content.op_getfield(jitstate, fielddesc)
if box is not None:
@@ -199,6 +219,7 @@
return box
def op_setfield(self, jitstate, fielddesc, valuebox):
+ self.known_nonzero = True
gv_ptr = self.genvar
if gv_ptr:
fielddesc.generate_set(jitstate, gv_ptr,
@@ -208,6 +229,7 @@
self.content.op_setfield(jitstate, fielddesc, valuebox)
def op_getsubstruct(self, jitstate, fielddesc):
+ self.known_nonzero = True
gv_ptr = self.genvar
if gv_ptr:
return fielddesc.generate_getsubstruct(jitstate, gv_ptr)
@@ -228,7 +250,7 @@
try:
result = boxmemo[self]
except KeyError:
- result = PtrRedBox(self.kind, self.genvar)
+ result = PtrRedBox(self.kind, self.genvar, self.known_nonzero)
boxmemo[self] = result
if self.content:
result.content = self.content.copy(memo)
@@ -263,12 +285,13 @@
elif self.genvar.is_const:
result = FrozenPtrConst(self.kind, self.genvar)
elif content is None:
- result = FrozenPtrVar(self.kind)
+ result = FrozenPtrVar(self.kind, self.known_nonzero)
else:
# if self.content is not None, it's a PartialDataStruct
from pypy.jit.timeshifter import rcontainer
assert isinstance(content, rcontainer.PartialDataStruct)
- result = FrozenPtrVarWithPartialData(self.kind)
+ result = FrozenPtrVarWithPartialData(self.kind,
+ known_nonzero=True)
boxmemo[self] = result
result.fz_partialcontent = content.partialfreeze(memo)
return result
@@ -286,11 +309,23 @@
assert self.genvar
return self.genvar
- def forcevar(self, jitstate, memo):
+ def forcevar(self, jitstate, memo, forget_nonzeroness):
from pypy.jit.timeshifter import rcontainer
# xxx
assert not isinstance(self.content, rcontainer.VirtualizableStruct)
- return RedBox.forcevar(self, jitstate, memo)
+ if self.is_constant():
+ # cannot mutate constant boxes in-place
+ builder = jitstate.curbuilder
+ box = self.copy(memo)
+ box.genvar = builder.genop_same_as(self.kind, self.genvar)
+ else:
+ # force virtual containers
+ self.getgenvar(jitstate)
+ box = self
+
+ if forget_nonzeroness:
+ box.known_nonzero = False
+ return box
def enter_block(self, incoming, memo):
if self.genvar:
@@ -412,6 +447,8 @@
def exactmatch(self, box, outgoingvarboxes, memo):
assert isinstance(box, PtrRedBox)
memo.partialdatamatch[box] = None # could do better
+ if self.is_constant_nullptr():
+ memo.forget_nonzeroness[box] = None
match = FrozenConst.exactmatch(self, box, outgoingvarboxes, memo)
if not memo.force_merge and not match:
from pypy.jit.timeshifter.rcontainer import VirtualContainer
@@ -425,10 +462,18 @@
class FrozenPtrVar(FrozenVar):
+ def __init__(self, kind, known_nonzero):
+ self.kind = kind
+ self.known_nonzero = known_nonzero
+
def exactmatch(self, box, outgoingvarboxes, memo):
assert isinstance(box, PtrRedBox)
memo.partialdatamatch[box] = None
+ if not self.known_nonzero:
+ memo.forget_nonzeroness[box] = None
match = FrozenVar.exactmatch(self, box, outgoingvarboxes, memo)
+ if self.known_nonzero and not box.known_nonzero:
+ match = False
if not memo.force_merge and not match:
from pypy.jit.timeshifter.rcontainer import VirtualContainer
if isinstance(box.content, VirtualContainer):
@@ -438,7 +483,7 @@
def unfreeze(self, incomingvarboxes, memo):
memo = memo.boxes
if self not in memo:
- newbox = PtrRedBox(self.kind, None)
+ newbox = PtrRedBox(self.kind, None, self.known_nonzero)
incomingvarboxes.append(newbox)
memo[self] = newbox
return newbox
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_exception.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_exception.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_exception.py Fri Feb 2 20:59:02 2007
@@ -140,26 +140,14 @@
self.check_insns(malloc=0)
def test_not_segregated_malloc_exception_path(self):
- py.test.skip("WIP")
- class E(Exception):
- def __init__(self, msg):
- self.msg = msg
-
def help(l, x):
- if x < 0:
- raise E("x negative: %d" %x)
- l.append(x)
- return l
+ l.append("x is %s" % chr(x))
def ll_function(x):
l = []
- l = help(l, x)
+ help(l, x)
return len(l)+x
res = self.timeshift(ll_function, [5], [], policy=P_OOPSPEC)
res == 6
self.check_oops(newlist=0)
-
-
-
-
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_promotion.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_promotion.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_promotion.py Fri Feb 2 20:59:02 2007
@@ -302,7 +302,6 @@
assert res == 22
def test_raise_result_mixup(self):
- py.test.skip("WIP")
def w(x):
pass
class E(Exception):
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py Fri Feb 2 20:59:02 2007
@@ -785,14 +785,14 @@
res = self.timeshift(ll_function, [21, -21, 0], [],
policy=P_NOVIRTUAL)
assert res == 42
- self.check_insns({'malloc_varsize': 1, 'ptr_iszero': 1,
+ self.check_insns({'malloc_varsize': 1,
'setarrayitem': 2, 'getarrayitem': 1,
'getarraysize': 1, 'int_mul': 1})
res = self.timeshift(ll_function, [21, -21, 1], [],
policy=P_NOVIRTUAL)
assert res == -42
- self.check_insns({'malloc_varsize': 1, 'ptr_iszero': 1,
+ self.check_insns({'malloc_varsize': 1,
'setarrayitem': 2, 'getarrayitem': 1,
'getarraysize': 1, 'int_mul': 1})
@@ -808,7 +808,7 @@
res = self.timeshift(ll_function, [21, -21, 0], [],
policy=P_NOVIRTUAL)
assert res == 42
- self.check_insns({'malloc_varsize': 1, 'ptr_iszero': 1,
+ self.check_insns({'malloc_varsize': 1,
'getarraysubstruct': 3,
'setfield': 2, 'getfield': 1,
'getarraysize': 1, 'int_mul': 1})
@@ -816,7 +816,7 @@
res = self.timeshift(ll_function, [21, -21, 1], [],
policy=P_NOVIRTUAL)
assert res == -42
- self.check_insns({'malloc_varsize': 1, 'ptr_iszero': 1,
+ self.check_insns({'malloc_varsize': 1,
'getarraysubstruct': 3,
'setfield': 2, 'getfield': 1,
'getarraysize': 1, 'int_mul': 1})
@@ -1292,3 +1292,59 @@
res = self.timeshift(f, [3], [], policy=P_NOVIRTUAL)
assert res == '2'
+
+ def test_known_nonzero(self):
+ S = lltype.GcStruct('s', ('x', lltype.Signed))
+ global_s = lltype.malloc(S, immortal=True)
+ global_s.x = 100
+
+ def h():
+ s = lltype.malloc(S)
+ s.x = 50
+ return s
+ def g(s, y):
+ if s:
+ return s.x * 5
+ else:
+ return -12 + y
+ def f(x, y):
+ x = hint(x, concrete=True)
+ if x == 1:
+ return g(lltype.nullptr(S), y)
+ elif x == 2:
+ return g(global_s, y)
+ elif x == 3:
+ s = lltype.malloc(S)
+ s.x = y
+ return g(s, y)
+ elif x == 4:
+ s = h()
+ return g(s, y)
+ else:
+ s = h()
+ if s:
+ return g(s, y)
+ else:
+ return 0
+
+ P = StopAtXPolicy(h)
+
+ res = self.timeshift(f, [1, 10], [0], policy=P)
+ assert res == -2
+ self.check_insns(int_mul=0, int_add=1)
+
+ res = self.timeshift(f, [2, 10], [0], policy=P)
+ assert res == 500
+ self.check_insns(int_mul=1, int_add=0)
+
+ res = self.timeshift(f, [3, 10], [0], policy=P)
+ assert res == 50
+ self.check_insns(int_mul=1, int_add=0)
+
+ res = self.timeshift(f, [4, 10], [0], policy=P)
+ assert res == 250
+ self.check_insns(int_mul=1, int_add=1)
+
+ res = self.timeshift(f, [5, 10], [0], policy=P)
+ assert res == 250
+ self.check_insns(int_mul=1, int_add=0)
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py Fri Feb 2 20:59:02 2007
@@ -53,6 +53,7 @@
return self.raise_analyzer.analyze(op)
def transform(self):
+ self.simplify_operations()
self.compute_merge_points()
self.insert_save_return()
self.insert_splits()
@@ -109,6 +110,23 @@
if startblock in global_merge_blocks:
self.mergepoint_set[startblock] = 'global'
+ def simplify_operations(self):
+ # ptr_eq(x, 0) => ptr_iszero
+ # ptr_ne(x, 0) => ptr_nonzero
+ replace = {'ptr_eq': 'ptr_iszero',
+ 'ptr_ne': 'ptr_nonzero'}
+ for block in self.graph.iterblocks():
+ for op in block.operations:
+ if op.opname in replace:
+ srcargs = op.args
+ for v1, v2 in [(srcargs[0], srcargs[1]),
+ (srcargs[1], srcargs[0])]:
+ if isinstance(v2, Constant):
+ if not v2.value:
+ op.opname = replace[op.opname]
+ op.args = [v1]
+ break
+
def graph_calling_color(self, tsgraph):
args_hs, hs_res = self.hannotator.bookkeeper.tsgraphsigs[tsgraph]
if originalconcretetype(hs_res) is lltype.Void:
@@ -244,51 +262,58 @@
if not hs_switch.is_green():
self.insert_split_handling(block)
+ def trace_back_exitswitch(self, block):
+ """Return the (opname, arguments) that created the exitswitch of
+ the block. The opname is None if not found.
+ """
+ v = block.exitswitch
+ inverted = False
+ for i in range(len(block.operations)-1, -1, -1):
+ op = block.operations[i]
+ if op.result is v:
+ if op.opname == 'bool_not':
+ inverted = not inverted
+ [v] = op.args
+ elif op.opname == 'same_as':
+ [v] = op.args
+ else:
+ opname = op.opname
+ opargs = op.args
+ if inverted:
+ opname = {'ptr_nonzero': 'ptr_iszero',
+ 'ptr_iszero' : 'ptr_nonzero'}.get(opname)
+ return opname, opargs # found
+ # not found, comes from earlier block - give up
+ return None, None
+
def insert_split_handling(self, block):
- # lots of clever in-line logic commented out
v_redswitch = block.exitswitch
+
+ # try to look where the v_redswitch comes from
+ split_variant = ''
+ split_extras = []
+ srcopname, srcargs = self.trace_back_exitswitch(block)
+ if srcopname == 'ptr_nonzero':
+ split_variant = '_ptr_nonzero'
+ split_extras = srcargs
+ elif srcopname == 'ptr_iszero':
+ split_variant = '_ptr_iszero'
+ split_extras = srcargs
+
link_f, link_t = block.exits
if link_f.exitcase:
link_f, link_t = link_t, link_f
assert link_f.exitcase is False
assert link_t.exitcase is True
-## constant_block = Block([])
-## nonconstant_block = Block([])
-
-## v_flag = self.genop(block, 'is_constant', [v_redswitch],
-## resulttype = lltype.Bool)
-## self.genswitch(block, v_flag, true = constant_block,
-## false = nonconstant_block)
-
-## v_greenswitch = self.genop(constant_block, 'revealconst',
-## [v_redswitch],
-## resulttype = lltype.Bool)
-## constant_block.exitswitch = v_greenswitch
-## constant_block.closeblock(link_f, link_t)
-
reds, greens = self.sort_by_color(link_f.args, link_f.target.inputargs)
self.genop(block, 'save_locals', reds)
resumepoint = self.get_resume_point(link_f.target)
c_resumepoint = inputconst(lltype.Signed, resumepoint)
- v_flag = self.genop(block, 'split',
- [v_redswitch, c_resumepoint] + greens,
- resulttype = lltype.Bool)
-
+ v_flag = self.genop(block, 'split' + split_variant,
+ [v_redswitch, c_resumepoint] + split_extras + greens,
+ resulttype = lltype.Bool)
block.exitswitch = v_flag
-## true_block = Block([])
-## true_link = Link([], true_block)
-## true_link.exitcase = True
-## true_link.llexitcase = True
-## block.recloseblock(link_f, true_link)
-
-## reds, greens = self.sort_by_color(link_t.args)
-## self.genop(true_block, 'save_locals', reds)
-## self.genop(true_block, 'enter_block', [])
-## true_block.closeblock(Link(link_t.args, link_t.target))
-
-## SSA_to_SSI({block : True, # reachable from outside
-## true_block: False}, self.hannotator)
def get_resume_point_link(self, block):
try:
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/vdict.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/vdict.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/vdict.py Fri Feb 2 20:59:02 2007
@@ -133,7 +133,7 @@
def factory(self):
vdict = self.VirtualDict(self)
- box = rvalue.PtrRedBox(self.ptrkind)
+ box = rvalue.PtrRedBox(self.ptrkind, known_nonzero=True)
box.content = vdict
vdict.ownbox = box
return box
@@ -208,7 +208,7 @@
gv_dict = builder.genop_call(typedesc.tok_ll_newdict,
typedesc.gv_ll_newdict,
args_gv)
- self.ownbox.genvar = gv_dict
+ self.ownbox.setgenvar_hint(gv_dict, known_nonzero=True)
self.ownbox.content = None
for gv_key, valuebox, hash in items:
gv_hash = builder.rgenop.genconst(hash)
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/vlist.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/vlist.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/vlist.py Fri Feb 2 20:59:02 2007
@@ -75,7 +75,7 @@
def factory(self, length, itembox):
vlist = VirtualList(self, length, itembox)
- box = rvalue.PtrRedBox(self.ptrkind)
+ box = rvalue.PtrRedBox(self.ptrkind, known_nonzero=True)
box.content = vlist
vlist.ownbox = box
return box
@@ -154,7 +154,7 @@
def setforced(self, gv_forced):
self.item_boxes = None
- self.ownbox.genvar = gv_forced
+ self.ownbox.setgenvar_hint(gv_forced, known_nonzero=True)
self.ownbox.content = None
def force_runtime_container(self, jitstate):
Modified: pypy/branch/jit-virtual-world/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/rpython/lltypesystem/rclass.py (original)
+++ pypy/branch/jit-virtual-world/pypy/rpython/lltypesystem/rclass.py Fri Feb 2 20:59:02 2007
@@ -58,7 +58,7 @@
OBJECT_VTABLE = lltype.ForwardReference()
CLASSTYPE = Ptr(OBJECT_VTABLE)
OBJECT = GcStruct('object', ('typeptr', CLASSTYPE),
- hints = {'immutable': True})
+ hints = {'immutable': True, 'shouldntbenull': True})
OBJECTPTR = Ptr(OBJECT)
OBJECT_VTABLE.become(Struct('object_vtable',
#('parenttypeptr', CLASSTYPE),
More information about the pypy-svn
mailing list