[pypy-svn] r37966 - in pypy/branch/jit-virtual-world/pypy: jit/timeshifter jit/timeshifter/test rpython translator/c
arigo at codespeak.net
arigo at codespeak.net
Mon Feb 5 15:24:03 CET 2007
Author: arigo
Date: Mon Feb 5 15:23:58 2007
New Revision: 37966
Added:
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/exception.py (contents, props changed)
Modified:
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py
pypy/branch/jit-virtual-world/pypy/jit/timeshifter/oop.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/test/test_portal.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/rpython/llinterp.py
pypy/branch/jit-virtual-world/pypy/translator/c/exceptiontransform.py
Log:
(pedronis, arre, arigo)
* simplify exceptiontransform to use a Struct instead of an RPyhton
instance to store the current exception.
* after residual calls, if possible, we check for exceptions using
promotion. This allows the JIT compiler to only produce code
for the branch that is actually taken (i.e. the non-exceptional
branch, usually).
Added: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/exception.py
==============================================================================
--- (empty file)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/exception.py Mon Feb 5 15:23:58 2007
@@ -0,0 +1,76 @@
+from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.jit.timeshifter import rvalue, rtimeshift
+
+
+class ExceptionDesc:
+
+ def __init__(self, hrtyper, lazy_exception_path):
+ RGenOp = hrtyper.RGenOp
+ self.etrafo = hrtyper.annotator.exceptiontransformer
+ self.cexcdata = self.etrafo.cexcdata
+ self.exc_data_ptr = self.cexcdata.value
+ self.gv_excdata = RGenOp.constPrebuiltGlobal(self.exc_data_ptr)
+
+ EXCDATA = self.etrafo.EXCDATA
+ self.exc_type_token = RGenOp.fieldToken(EXCDATA, 'exc_type')
+ self.exc_value_token = RGenOp.fieldToken(EXCDATA, 'exc_value')
+ self.exc_type_kind = RGenOp.kindToken(EXCDATA.exc_type)
+ self.exc_value_kind = RGenOp.kindToken(EXCDATA.exc_value)
+
+ LL_EXC_TYPE = EXCDATA.exc_type
+ LL_EXC_VALUE = EXCDATA.exc_value
+
+ self.gv_null_exc_type = RGenOp.constPrebuiltGlobal(
+ lltype.nullptr(LL_EXC_TYPE.TO))
+ self.gv_null_exc_value = RGenOp.constPrebuiltGlobal(
+ lltype.nullptr(LL_EXC_VALUE.TO))
+ self.null_exc_type_box = rvalue.PtrRedBox(self.exc_type_kind,
+ self.gv_null_exc_type)
+ self.null_exc_value_box = rvalue.PtrRedBox(self.exc_value_kind,
+ self.gv_null_exc_value)
+ self.lazy_exception_path = lazy_exception_path
+
+ def _freeze_(self):
+ return True
+
+ def genop_get_exc_type(self, builder):
+ return builder.genop_getfield(self.exc_type_token, self.gv_excdata)
+
+ def genop_get_exc_value(self, builder):
+ return builder.genop_getfield(self.exc_value_token, self.gv_excdata)
+
+ def genop_set_exc_type(self, builder, gv_value):
+ builder.genop_setfield(self.exc_type_token, self.gv_excdata, gv_value)
+
+ def genop_set_exc_value(self, builder, gv_value):
+ builder.genop_setfield(self.exc_value_token, self.gv_excdata, gv_value)
+
+ def fetch_global_excdata(self, jitstate, known_occurred=False):
+ builder = jitstate.curbuilder
+ gv_etype = self.genop_get_exc_type (builder)
+ gv_evalue = self.genop_get_exc_value(builder)
+ self.genop_set_exc_type (builder, self.gv_null_exc_type )
+ self.genop_set_exc_value(builder, self.gv_null_exc_value)
+ etypebox = rvalue.PtrRedBox(self.exc_type_kind, gv_etype )
+ evaluebox = rvalue.PtrRedBox(self.exc_value_kind, gv_evalue)
+ etypebox .known_nonzero = known_occurred
+ evaluebox.known_nonzero = known_occurred
+ rtimeshift.setexctypebox (jitstate, etypebox)
+ rtimeshift.setexcvaluebox(jitstate, evaluebox)
+
+ def store_global_excdata(self, jitstate):
+ builder = jitstate.curbuilder
+ etypebox = jitstate.exc_type_box
+ if etypebox.is_constant():
+ ll_etype = rvalue.ll_getvalue(etypebox, llmemory.Address)
+ if not ll_etype:
+ return # we know there is no exception set
+ evaluebox = jitstate.exc_value_box
+ gv_etype = etypebox .getgenvar(jitstate)
+ gv_evalue = evaluebox.getgenvar(jitstate)
+ self.genop_set_exc_type (builder, gv_etype )
+ self.genop_set_exc_value(builder, gv_evalue)
+
+ def gen_exc_occurred(self, builder):
+ gv_etype = self.genop_get_exc_type(builder)
+ return builder.genop_ptr_nonzero(self.exc_type_kind, gv_etype)
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 Mon Feb 5 15:23:58 2007
@@ -22,6 +22,7 @@
from pypy.jit.hintannotator.model import originalconcretetype
from pypy.jit.timeshifter import rtimeshift, rvalue, rcontainer, oop
from pypy.jit.timeshifter.transform import HintGraphTransformer
+from pypy.jit.timeshifter.exception import ExceptionDesc
from pypy.jit.codegen import model as cgmodel
class HintTypeSystem(LowLevelTypeSystem):
@@ -77,69 +78,13 @@
(self.s_Queue,
self.r_Queue) = self.s_r_instanceof(rtimeshift.BaseDispatchQueue)
- self.etrafo = hannotator.exceptiontransformer
- self.cexcdata = self.etrafo.cexcdata
- self.exc_data_ptr = self.cexcdata.value
- gv_excdata = RGenOp.constPrebuiltGlobal(self.exc_data_ptr)
- LL_EXC_TYPE = rtyper.exceptiondata.lltype_of_exception_type
- LL_EXC_VALUE = rtyper.exceptiondata.lltype_of_exception_value
- null_exc_type_box = rvalue.redbox_from_prebuilt_value(RGenOp,
- lltype.nullptr(LL_EXC_TYPE.TO))
- null_exc_value_box = rvalue.redbox_from_prebuilt_value(RGenOp,
- lltype.nullptr(LL_EXC_VALUE.TO))
-
- p = self.etrafo.rpyexc_fetch_type_ptr.value
- gv_rpyexc_fetch_type = RGenOp.constPrebuiltGlobal(p)
- tok_fetch_type = RGenOp.sigToken(lltype.typeOf(p).TO)
- kind_etype = RGenOp.kindToken(LL_EXC_TYPE)
-
- p = self.etrafo.rpyexc_fetch_value_ptr.value
- gv_rpyexc_fetch_value = RGenOp.constPrebuiltGlobal(p)
- tok_fetch_value = RGenOp.sigToken(lltype.typeOf(p).TO)
- kind_evalue = RGenOp.kindToken(LL_EXC_VALUE)
-
- p = self.etrafo.rpyexc_clear_ptr.value
- gv_rpyexc_clear = RGenOp.constPrebuiltGlobal(p)
- tok_clear = RGenOp.sigToken(lltype.typeOf(p).TO)
-
- p = self.etrafo.rpyexc_raise_ptr.value
- gv_rpyexc_raise = RGenOp.constPrebuiltGlobal(p)
- tok_raise = RGenOp.sigToken(lltype.typeOf(p).TO)
-
- def fetch_global_excdata(jitstate):
- builder = jitstate.curbuilder
- gv_etype = builder.genop_call(tok_fetch_type,
- gv_rpyexc_fetch_type, [])
- gv_evalue = builder.genop_call(tok_fetch_value,
- gv_rpyexc_fetch_value, [])
- builder.genop_call(tok_clear, gv_rpyexc_clear, [])
- etypebox = rvalue.PtrRedBox(kind_etype, gv_etype)
- evaluebox = rvalue.PtrRedBox(kind_evalue, gv_evalue)
- rtimeshift.setexctypebox (jitstate, etypebox)
- rtimeshift.setexcvaluebox(jitstate, evaluebox)
- self.fetch_global_excdata = fetch_global_excdata
-
- def store_global_excdata(jitstate):
- builder = jitstate.curbuilder
- etypebox = jitstate.exc_type_box
- if etypebox.is_constant():
- ll_etype = rvalue.ll_getvalue(etypebox, llmemory.Address)
- if not ll_etype:
- return # we known there is no exception set
- evaluebox = jitstate.exc_value_box
- gv_etype = etypebox .getgenvar(jitstate)
- gv_evalue = evaluebox.getgenvar(jitstate)
- builder.genop_call(tok_raise,
- gv_rpyexc_raise, [gv_etype, gv_evalue])
- self.store_global_excdata = store_global_excdata
-
- def ll_fresh_jitstate(builder):
+ def ll_fresh_jitstate(builder, exceptiondesc):
return rtimeshift.JITState(builder, None,
- null_exc_type_box,
- null_exc_value_box)
+ exceptiondesc.null_exc_type_box,
+ exceptiondesc.null_exc_value_box)
self.ll_fresh_jitstate = ll_fresh_jitstate
- def ll_finish_jitstate(jitstate, graphsigtoken):
+ def ll_finish_jitstate(jitstate, exceptiondesc, graphsigtoken):
assert jitstate.resuming is None
returnbox = rtimeshift.getreturnbox(jitstate)
gv_ret = returnbox.getgenvar(jitstate)
@@ -149,7 +94,7 @@
content = virtualizable_box.content
assert isinstance(content, rcontainer.VirtualizableStruct)
content.store_back(jitstate)
- store_global_excdata(jitstate)
+ exceptiondesc.store_global_excdata(jitstate)
jitstate.curbuilder.finish_and_return(graphsigtoken, gv_ret)
self.ll_finish_jitstate = ll_finish_jitstate
@@ -200,6 +145,9 @@
"Forgot 'hint(None, global_merge_point=True)'?")
self.log.event("Timeshifted control flow of %d graphs." % (len(seen),))
+ self.exceptiondesc = ExceptionDesc(self,
+ self.portal_contains_global_mp)
+
#import pdb; pdb.set_trace()
# only keep the hint-annotated graphs that are really useful
self.annotator.translator.graphs = [graph
@@ -277,6 +225,7 @@
args_specification = unrolling_iterable(args_specification)
fresh_jitstate = self.ll_fresh_jitstate
finish_jitstate = self.ll_finish_jitstate
+ exceptiondesc = self.exceptiondesc
sigtoken = rgenop.sigToken(FUNC)
# debug helper
@@ -323,7 +272,7 @@
builder, gv_generated, inputargs_gv = rgenop.newgraph(sigtoken,
"generated")
cache[key] = gv_generated
- top_jitstate = fresh_jitstate(builder)
+ top_jitstate = fresh_jitstate(builder, exceptiondesc)
i = 0
for color, _, make_arg_redbox in args_specification:
if color == "green":
@@ -350,7 +299,7 @@
builder.start_writing()
top_jitstate = portal_fn(top_jitstate, *portal_ts_args)
if top_jitstate is not None:
- finish_jitstate(top_jitstate, sigtoken)
+ finish_jitstate(top_jitstate, exceptiondesc, sigtoken)
builder.end()
builder.show_incremental_progress()
@@ -379,7 +328,7 @@
TYPES = [v.concretetype for v in origportalgraph.getargs()]
argspecandtypes = unrolling_iterable(zip(args_specification,
TYPES))
- fetch_global_excdata = self.fetch_global_excdata
+ fetch_global_excdata = self.exceptiondesc.fetch_global_excdata
def portalreentry(jitstate, *args): # xxx virtualizables?
i = 0
@@ -419,7 +368,7 @@
i += 1
portal_ts_args += (box,)
- top_jitstate = fresh_jitstate(builder)
+ top_jitstate = fresh_jitstate(builder, exceptiondesc)
state.graph_compilation_queue.append((top_jitstate, portal_ts_args))
gv_res = curbuilder.genop_call(sigtoken, gv_generated, args_gv)
@@ -713,12 +662,12 @@
if isinstance(hop.args_r[0], BlueRepr):
return hop.args_r[0].timeshift_getfield(hop)
ts = self
- if hop.args_v[0] == ts.cexcdata:
+ if hop.args_v[0] == ts.exceptiondesc.cexcdata:
# reading one of the exception boxes (exc_type or exc_value)
fieldname = hop.args_v[1].value
- if fieldname.endswith('exc_type'):
+ if fieldname == 'exc_type':
reader = rtimeshift.getexctypebox
- elif fieldname.endswith('exc_value'):
+ elif fieldname == 'exc_value':
reader = rtimeshift.getexcvaluebox
else:
raise Exception("getfield(exc_data, %r)" % (fieldname,))
@@ -793,12 +742,12 @@
VALUETYPE = originalconcretetype(hop.args_s[2])
if VALUETYPE is lltype.Void:
return
- if hop.args_v[0] == ts.cexcdata:
+ if hop.args_v[0] == ts.exceptiondesc.cexcdata:
# reading one of the exception boxes (exc_type or exc_value)
fieldname = hop.args_v[1].value
- if fieldname.endswith('exc_type'):
+ if fieldname == 'exc_type':
writer = rtimeshift.setexctypebox
- elif fieldname.endswith('exc_value'):
+ elif fieldname == 'exc_value':
writer = rtimeshift.setexcvaluebox
else:
raise Exception("setfield(exc_data, %r)" % (fieldname,))
@@ -1207,6 +1156,7 @@
RESIDUAL_FUNCTYPE = self.get_residual_functype(tsgraph)
residualSigToken = self.RGenOp.sigToken(RESIDUAL_FUNCTYPE)
ll_finish_jitstate = self.ll_finish_jitstate
+ exceptiondesc = self.exceptiondesc
args_s = [self.s_JITState] + [annmodel.lltype_to_annotation(ARG)
for ARG in TS_FUNC.TO.ARGS[1:]]
@@ -1220,7 +1170,8 @@
jitstate.resumepoint = N
finaljitstate = tsfn(jitstate, *dummy_args)
if finaljitstate is not None:
- ll_finish_jitstate(finaljitstate, residualSigToken)
+ ll_finish_jitstate(finaljitstate, exceptiondesc,
+ residualSigToken)
return self.translate_op_merge_point(hop,
global_resumer = call_for_global_resuming)
@@ -1277,15 +1228,19 @@
# handling of the various kinds of calls
def translate_op_oopspec_was_residual(self, hop):
- return hop.inputconst(lltype.Bool, False)
+ v_jitstate = hop.llops.getjitstate()
+ return hop.llops.genmixlevelhelpercall(rtimeshift.oopspec_was_residual,
+ [self.s_JITState],
+ [v_jitstate ],
+ annmodel.s_Bool)
- def translate_op_oopspec_call(self, hop):
+ def translate_op_oopspec_call(self, hop, can_raise=True):
# special-cased call, for things like list methods
from pypy.jit.timeshifter.oop import OopSpecDesc, Index
c_func = hop.args_v[0]
fnobj = c_func.value._obj
- oopspecdesc = OopSpecDesc(self, fnobj)
+ oopspecdesc = OopSpecDesc(self, fnobj, can_raise)
hop.r_s_popfirstarg()
args_v = []
@@ -1343,6 +1298,9 @@
[v_jitstate, c_oopspecdesc] + args_v,
s_result)
+ def translate_op_oopspec_call_noexc(self, hop):
+ return self.translate_op_oopspec_call(hop, False)
+
def translate_op_green_call(self, hop):
for r_arg in hop.args_r:
assert isinstance(r_arg, GreenRepr)
@@ -1427,27 +1385,32 @@
oop = dopts['oop']
v_jitstate = hop.llops.getjitstate()
if withexc:
- hop.llops.genmixlevelhelpercall(self.fetch_global_excdata,
- [self.s_JITState], [v_jitstate],
- annmodel.s_None)
- if not oop:
- v_after = hop.llops.genmixlevelhelpercall(
- rtimeshift.after_residual_call,
- [self.s_JITState],
- [v_jitstate],
- self.s_RedBox)
- else: # xxx
- v_after = hop.inputconst(self.getredrepr(lltype.Signed), 0)
-
+ c_exception_desc = hop.inputconst(lltype.Void, self.exceptiondesc)
+ else:
+ c_exception_desc = hop.inputconst(lltype.Void, None)
+ bk = self.rtyper.annotator.bookkeeper
+ s_exception_desc = bk.immutablevalue(c_exception_desc.value)
+ c_check_forced = hop.inputconst(lltype.Bool, not oop)
+ v_after = hop.llops.genmixlevelhelpercall(
+ rtimeshift.ll_after_residual_call,
+ [self.s_JITState, s_exception_desc, annmodel.s_Bool],
+ [v_jitstate , c_exception_desc, c_check_forced ],
+ self.s_RedBox)
return v_after
-
- def translate_op_reshape(self, hop):
- v_jitstate = hop.llops.getjitstate()
- v_shape, = hop.inputargs(self.getredrepr(lltype.Signed))
- return hop.llops.genmixlevelhelpercall(rtimeshift.reshape,
- [self.s_JITState, self.s_RedBox],
- [v_jitstate , v_shape ],
- annmodel.s_None)
+
+ def translate_op_residual_fetch(self, hop):
+ dopts = hop.args_v[1].value
+ oop = dopts['oop']
+ v_jitstate = hop.llops.getjitstate()
+ v_flags = hop.inputarg(self.getredrepr(lltype.Signed), arg=0)
+ bk = self.rtyper.annotator.bookkeeper
+ c_exception_desc = hop.inputconst(lltype.Void, self.exceptiondesc)
+ s_exception_desc = bk.immutablevalue(c_exception_desc.value)
+ c_check_forced = hop.inputconst(lltype.Bool, not oop)
+ return hop.llops.genmixlevelhelpercall(rtimeshift.residual_fetch,
+ [self.s_JITState, s_exception_desc, annmodel.s_Bool, self.s_RedBox],
+ [v_jitstate , c_exception_desc, c_check_forced , v_flags ],
+ annmodel.s_None)
def translate_op_reverse_split_queue(self, hop):
hop.llops.genmixlevelhelpercall(rtimeshift.reverse_split_queue,
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/oop.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/oop.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/oop.py Mon Feb 5 15:23:58 2007
@@ -16,11 +16,13 @@
do_call = None
- def __init__(self, hrtyper, fnobj):
+ def __init__(self, hrtyper, fnobj, can_raise):
ll_func = fnobj._callable
FUNCTYPE = lltype.typeOf(fnobj)
nb_args = len(FUNCTYPE.ARGS)
+ self.can_raise = can_raise
+
# parse the oopspec and fill in the arguments
operation_name, args = ll_func.oopspec.split('(', 1)
assert args.endswith(')')
@@ -79,12 +81,6 @@
self.ll_handler = getattr(vmodule, method)
self.couldfold = getattr(self.ll_handler, 'couldfold', False)
- # exception handling
- graph = fnobj.graph
- etrafo = hrtyper.etrafo
- self.can_raise = etrafo.raise_analyzer.analyze_direct_call(graph)
- self.fetch_global_excdata = hrtyper.fetch_global_excdata
-
if self.couldfold:
ARGS = FUNCTYPE.ARGS
residualargsources = self.residualargsources
@@ -129,7 +125,7 @@
return self.errorbox
gv_result = builder.genop_call(self.sigtoken, self.gv_fnptr, args_gv)
if self.can_raise:
- self.fetch_global_excdata(jitstate)
+ jitstate.generated_oop_residual_can_raise = True
return self.redboxbuilder(self.result_kind, gv_result)
def residual_exception(self, jitstate, ExcCls):
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 Mon Feb 5 15:23:58 2007
@@ -759,7 +759,7 @@
access_token = typedesc.access_desc.fieldtoken
builder.genop_setfield(access_token, gv_outside, typedesc.gv_access)
- def after_residual_call(self, jitstate):
+ def check_forced_after_residual_call(self, jitstate):
typedesc = self.typedesc
builder = jitstate.curbuilder
gv_outside = self.content_boxes[-1].genvar
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 Mon Feb 5 15:23:58 2007
@@ -518,12 +518,38 @@
gv_result = builder.genop_call(calldesc.sigtoken, gv_funcbox, args_gv)
return calldesc.redboxbuilder(calldesc.result_kind, gv_result)
-def after_residual_call(jitstate):
- return jitstate.after_residual_call()
-
-def reshape(jitstate, shapebox):
- shapemask = rvalue.ll_getvalue(shapebox, lltype.Signed)
- jitstate.reshape(shapemask)
+def ll_after_residual_call(jitstate, exceptiondesc, check_forced):
+ builder = jitstate.curbuilder
+ if check_forced:
+ gv_flags = jitstate.check_forced_after_residual_call()
+ else:
+ gv_flags = None
+ if exceptiondesc:
+ if exceptiondesc.lazy_exception_path:
+ gv_occurred = exceptiondesc.gen_exc_occurred(builder)
+ gv_flag = builder.genop1("cast_bool_to_int", gv_occurred)
+ if gv_flags is None:
+ gv_flags = gv_flag
+ else:
+ gv_flags = builder.genop2("int_or", gv_flags, gv_flag)
+ else:
+ exceptiondesc.fetch_global_excdata(jitstate)
+ if gv_flags is None:
+ gv_flags = builder.rgenop.constPrebuiltGlobal(0)
+ return rvalue.IntRedBox(builder.rgenop.kindToken(lltype.Signed), gv_flags)
+
+def residual_fetch(jitstate, exceptiondesc, check_forced, flagsbox):
+ flags = rvalue.ll_getvalue(flagsbox, lltype.Signed)
+ if flags & 1: # an exception occurred
+ exceptiondesc.fetch_global_excdata(jitstate, known_occurred=True)
+ if check_forced:
+ shapemask = flags & ~ 1
+ jitstate.reshape(shapemask)
+
+def oopspec_was_residual(jitstate):
+ res = jitstate.generated_oop_residual_can_raise
+ jitstate.generated_oop_residual_can_raise = False
+ return res
class ResumingInfo(object):
@@ -898,11 +924,13 @@
next
virtualizables
shape_place
+ generated_oop_residual_can_raise
""".split()
returnbox = None
next = None # for linked lists
promotion_path = None
+ generated_oop_residual_can_raise = False
def __init__(self, builder, frame, exc_type_box, exc_value_box,
resumepoint=-1, newgreens=[], resuming=None,
@@ -972,7 +1000,7 @@
if virtualizables:
builder = self.curbuilder
memo = rvalue.make_vrti_memo()
- memo.bitcount = 0
+ memo.bitcount = 1
memo.frameindex = 0
memo.framevars_gv = []
shape_kind = builder.rgenop.kindToken(lltype.Signed)
@@ -998,29 +1026,28 @@
assert isinstance(content, rcontainer.VirtualizableStruct)
content.prepare_for_residual_call(self, gv_base, vable_rti)
- def after_residual_call(self):
+ def check_forced_after_residual_call(self):
virtualizables = self.virtualizables
builder = self.curbuilder
if virtualizables:
for virtualizable_box in virtualizables:
content = virtualizable_box.content
assert isinstance(content, rcontainer.VirtualizableStruct)
- content.after_residual_call(self)
+ content.check_forced_after_residual_call(self)
shape_kind = builder.rgenop.kindToken(lltype.Signed)
gv_shape = builder.genop_absorb_place(shape_kind,
self.shape_place)
self.shape_place = None
+ return gv_shape
else:
- gv_shape = builder.rgenop.genconst(0)
- return rvalue.IntRedBox(builder.rgenop.kindToken(lltype.Signed),
- gv_shape)
+ return None
def reshape(self, shapemask):
virtualizables = self.virtualizables
builder = self.curbuilder
if virtualizables:
memo = rvalue.make_vrti_memo()
- memo.bitcount = 0
+ memo.bitcount = 1
if shapemask:
memo.forced = []
else:
Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_portal.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_portal.py (original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_portal.py Mon Feb 5 15:23:58 2007
@@ -64,8 +64,8 @@
self.hrtyper.specialize(origportalgraph=origportalgraph,
view = conftest.option.view and self.small)
- if conftest.option.view and self.small:
- t.view()
+ #if conftest.option.view and self.small:
+ # t.view()
self.postprocess_timeshifting()
self.readportalgraph = self.hrtyper.readportalgraph
@@ -86,12 +86,14 @@
backendoptimize=backendoptimize)
self.main_args = main_args
self.main_is_portal = main is portal
- llinterp = LLInterpreter(self.rtyper)
+ exc_data_ptr = self.hrtyper.exceptiondesc.exc_data_ptr
+ llinterp = LLInterpreter(self.rtyper, exc_data_ptr=exc_data_ptr)
res = llinterp.eval_graph(self.maingraph, main_args)
return res
def get_residual_graph(self):
- llinterp = LLInterpreter(self.rtyper)
+ exc_data_ptr = self.hrtyper.exceptiondesc.exc_data_ptr
+ llinterp = LLInterpreter(self.rtyper, exc_data_ptr=exc_data_ptr)
if self.main_is_portal:
residual_graph = llinterp.eval_graph(self.readportalgraph,
self.main_args)._obj.graph
@@ -469,3 +471,49 @@
res = self.timeshift_from_portal(ll_main, ll_function, [5], policy=P_NOVIRTUAL)
assert res == 123
self.check_insns(indirect_call=1)
+
+ def test_residual_red_call_with_promoted_exc(self):
+ def h(x):
+ if x > 0:
+ return x+1
+ else:
+ raise ValueError
+
+ def g(x):
+ return 2*h(x)
+
+ def f(x):
+ hint(None, global_merge_point=True)
+ try:
+ return g(x)
+ except ValueError:
+ return 7
+
+ stop_at_h = StopAtXPolicy(h)
+ res = self.timeshift_from_portal(f, f, [20], policy=stop_at_h)
+ assert res == 42
+ self.check_insns(int_add=0)
+
+ res = self.timeshift_from_portal(f, f, [-20], policy=stop_at_h)
+ assert res == 7
+ self.check_insns(int_add=0)
+
+ def test_residual_oop_raising(self):
+ def g(x):
+ lst = []
+ if x > 10:
+ lst.append(x)
+ return lst
+ def f(x):
+ hint(None, global_merge_point=True)
+ lst = g(x)
+ try:
+ return lst[0]
+ except IndexError:
+ return -42
+
+ res = self.timeshift_from_portal(f, f, [5], policy=P_OOPSPEC)
+ assert res == -42
+
+ res = self.timeshift_from_portal(f, f, [15], policy=P_OOPSPEC)
+ assert res == 15
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 Mon Feb 5 15:23:58 2007
@@ -106,6 +106,7 @@
hrtyper.specialize(view = conftest.option.view and self.small)
fresh_jitstate = hrtyper.ll_fresh_jitstate
finish_jitstate = hrtyper.ll_finish_jitstate
+ exceptiondesc = hrtyper.exceptiondesc
t = rtyper.annotator.translator
# make an interface to the timeshifted graphs:
@@ -180,11 +181,11 @@
i += 1
timeshifted_entrypoint_args += (box,)
- top_jitstate = fresh_jitstate(builder)
+ top_jitstate = fresh_jitstate(builder, exceptiondesc)
top_jitstate = timeshifted_entrypoint(top_jitstate,
*timeshifted_entrypoint_args)
if top_jitstate is not None:
- finish_jitstate(top_jitstate, sigtoken)
+ finish_jitstate(top_jitstate, exceptiondesc, sigtoken)
builder.end()
generated = gv_generated.revealconst(lltype.Ptr(FUNC))
@@ -220,9 +221,9 @@
self.rtyper = rtyper
self.hrtyper = hrtyper
self.annotate_interface_functions()
- if conftest.option.view and self.small:
- from pypy.translator.tool.graphpage import FlowGraphPage
- FlowGraphPage(t, ha.translator.graphs).display()
+ #if conftest.option.view and self.small:
+ # from pypy.translator.tool.graphpage import FlowGraphPage
+ # FlowGraphPage(t, ha.translator.graphs).display()
cache = self.__dict__.copy()
self._cache[key] = cache, getargtypes(rtyper.annotator, values)
@@ -267,12 +268,12 @@
residualargs.append(llvalue)
# run the graph generator
- llinterp = LLInterpreter(self.rtyper)
+ exc_data_ptr = self.hrtyper.exceptiondesc.exc_data_ptr
+ llinterp = LLInterpreter(self.rtyper, exc_data_ptr=exc_data_ptr)
ll_generated = llinterp.eval_graph(self.maingraph, mainargs)
# now try to run the residual graph generated by the builder
residual_graph = ll_generated._obj.graph
- residual_graph.exceptiontransformed = self.hrtyper.exc_data_ptr
self.ll_generated = ll_generated
self.residual_graph = residual_graph
if conftest.option.view:
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 Mon Feb 5 15:23:58 2007
@@ -672,7 +672,10 @@
def handle_oopspec_call(self, block, pos, withexc):
op = block.operations[pos]
assert op.opname == 'direct_call'
- op.opname = 'oopspec_call'
+ if withexc:
+ op.opname = 'oopspec_call'
+ else:
+ op.opname = 'oopspec_call_noexc'
if withexc:
link = split_block(self.hannotator, block, pos+1)
nextblock = link.target
@@ -765,19 +768,19 @@
oop = False):
dopts = {'withexc': withexc, 'oop': oop }
copts = Constant(dopts, lltype.Void)
- v_shape = self.genop(newops, 'after_residual_call', [copts],
+ v_flags = self.genop(newops, 'after_residual_call', [copts],
resulttype=lltype.Signed, red=True)
- reshape_index = len(newops)
- self.genop(newops, 'reshape', [v_shape])
- reshape_pos = pos+reshape_index
+ residual_fetch_index = len(newops)
+ self.genop(newops, 'residual_fetch', [v_flags, copts])
+ residual_fetch_pos = pos+residual_fetch_index
block.operations[pos:pos+1] = newops
- link = split_block(self.hannotator, block, reshape_pos)
+ link = split_block(self.hannotator, block, residual_fetch_pos)
nextblock = link.target
reds, greens = self.sort_by_color(link.args)
self.genop(block, 'save_locals', reds)
- v_finished_flag = self.genop(block, 'promote', [v_shape],
+ v_finished_flag = self.genop(block, 'promote', [v_flags],
resulttype = lltype.Bool)
self.go_to_dispatcher_if(block, v_finished_flag)
Modified: pypy/branch/jit-virtual-world/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/rpython/llinterp.py (original)
+++ pypy/branch/jit-virtual-world/pypy/rpython/llinterp.py Mon Feb 5 15:23:58 2007
@@ -42,10 +42,11 @@
class LLInterpreter(object):
""" low level interpreter working with concrete values. """
- def __init__(self, typer, heap=llheap, tracing=True):
+ def __init__(self, typer, heap=llheap, tracing=True, exc_data_ptr=None):
self.bindings = {}
self.typer = typer
self.heap = heap #module that provides malloc, etc for lltypes
+ self.exc_data_ptr = exc_data_ptr
self.active_frame = None
# XXX hack: set gc to None because
# prepare_graphs_and_create_gc might already use the llinterpreter!
@@ -150,6 +151,13 @@
self.active_frame = old_active_frame
raise ValueError, "couldn't match exception"
+ def get_transformed_exc_data(self, graph):
+ if hasattr(graph, 'exceptiontransformed'):
+ return graph.exceptiontransformed
+ if getattr(graph, 'rgenop', False):
+ return self.exc_data_ptr
+ return None
+
def checkptr(ptr):
assert isinstance(lltype.typeOf(ptr), lltype.Ptr)
@@ -284,18 +292,16 @@
raise LLException(etype, evalue)
resultvar, = block.getvariables()
result = self.getval(resultvar)
- if hasattr(self.graph, 'exceptiontransformed'):
+ exc_data = self.llinterpreter.get_transformed_exc_data(self.graph)
+ if exc_data:
# re-raise the exception set by this graph, if any
- exc_data = self.graph.exceptiontransformed
- etype = rclass.fishllattr(exc_data, 'exc_type')
+ etype = exc_data.exc_type
if etype:
- evalue = rclass.fishllattr(exc_data, 'exc_value')
+ evalue = exc_data.exc_value
if tracer:
tracer.dump('raise')
- rclass.feedllattr(exc_data, 'exc_type',
- lltype.typeOf(etype)._defl())
- rclass.feedllattr(exc_data, 'exc_value',
- lltype.typeOf(evalue)._defl())
+ exc_data.exc_type = lltype.typeOf(etype )._defl()
+ exc_data.exc_value = lltype.typeOf(evalue)._defl()
from pypy.translator.c import exceptiontransform
T = resultvar.concretetype
errvalue = exceptiontransform.error_value(T)
@@ -554,13 +560,13 @@
try:
return self.perform_call(f, FTYPE.ARGS, args)
except LLException, e:
- if hasattr(self.graph, 'exceptiontransformed'):
+ exc_data = self.llinterpreter.get_transformed_exc_data(self.graph)
+ if exc_data:
# store the LLException into the exc_data used by this graph
- exc_data = self.graph.exceptiontransformed
etype = e.args[0]
evalue = e.args[1]
- rclass.feedllattr(exc_data, 'exc_type', etype)
- rclass.feedllattr(exc_data, 'exc_value', evalue)
+ exc_data.exc_type = etype
+ exc_data.exc_value = evalue
from pypy.translator.c import exceptiontransform
return exceptiontransform.error_value(FTYPE.RESULT)
raise
Modified: pypy/branch/jit-virtual-world/pypy/translator/c/exceptiontransform.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/translator/c/exceptiontransform.py (original)
+++ pypy/branch/jit-virtual-world/pypy/translator/c/exceptiontransform.py Mon Feb 5 15:23:58 2007
@@ -9,6 +9,7 @@
from pypy.rpython.memory.lladdress import NULL
from pypy.rpython import rtyper
from pypy.rpython import rclass
+from pypy.rpython.rmodel import inputconst
from pypy.rlib.rarithmetic import r_uint, r_longlong, r_ulonglong
from pypy.annotation import model as annmodel
from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
@@ -45,25 +46,25 @@
mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper)
l2a = annmodel.lltype_to_annotation
- class ExcData(object):
- pass
- #exc_type = lltype.nullptr(self.exc_data.lltype_of_exception_type.TO)
- #exc_value = lltype.nullptr(self.exc_data.lltype_of_exception_value.TO)
+ EXCDATA = lltype.Struct('ExcData',
+ ('exc_type', self.lltype_of_exception_type),
+ ('exc_value', self.lltype_of_exception_value))
+ self.EXCDATA = EXCDATA
- exc_data = ExcData()
+ exc_data = lltype.malloc(EXCDATA, immortal=True)
null_type = lltype.nullptr(self.lltype_of_exception_type.TO)
null_value = lltype.nullptr(self.lltype_of_exception_value.TO)
def rpyexc_occured():
exc_type = exc_data.exc_type
- return exc_type is not null_type
+ return bool(exc_type)
# XXX tmp HACK for genllvm
# llvm is strongly typed between bools and ints, which means we have no way of
# calling rpyexc_occured() from c code with lltype.Bool
def _rpyexc_occured():
exc_type = exc_data.exc_type
- return exc_type is not null_type
+ return bool(exc_type)
def rpyexc_fetch_type():
return exc_data.exc_type
@@ -145,11 +146,8 @@
mixlevelannotator.finish()
- ExcDataDef = translator.annotator.bookkeeper.getuniqueclassdef(ExcData)
- self.ExcData_repr = rclass.getinstancerepr(translator.rtyper, ExcDataDef)
- self.exc_data_ptr = self.ExcData_repr.convert_const(exc_data)
- self.cexcdata = Constant(self.exc_data_ptr,
- self.ExcData_repr.lowleveltype)
+ self.exc_data_ptr = exc_data
+ self.cexcdata = Constant(exc_data, lltype.Ptr(EXCDATA))
self.lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping()
p = lltype.nullptr(self.lltype_of_exception_type.TO)
@@ -157,6 +155,15 @@
p = lltype.nullptr(self.lltype_of_exception_value.TO)
self.c_null_evalue = Constant(p, self.lltype_of_exception_value)
+ def gen_getfield(self, name, llops):
+ c_name = inputconst(lltype.Void, name)
+ return llops.genop('getfield', [self.cexcdata, c_name],
+ resulttype = getattr(self.EXCDATA, name))
+
+ def gen_setfield(self, name, v_value, llops):
+ c_name = inputconst(lltype.Void, name)
+ llops.genop('setfield', [self.cexcdata, c_name, v_value])
+
def transform_completely(self):
for graph in self.translator.graphs:
self.create_exception_handling(graph)
@@ -290,11 +297,10 @@
excblock = Block([])
llops = rtyper.LowLevelOpList(None)
- r = self.ExcData_repr
- var_value = r.getfield(self.cexcdata, 'exc_value', llops)
- var_type = r.getfield(self.cexcdata, 'exc_type', llops)
- r.setfield(self.cexcdata, 'exc_value', self.c_null_evalue, llops)
- r.setfield(self.cexcdata, 'exc_type', self.c_null_etype, llops)
+ var_value = self.gen_getfield('exc_value', llops)
+ var_type = self.gen_getfield('exc_type' , llops)
+ self.gen_setfield('exc_value', self.c_null_evalue, llops)
+ self.gen_setfield('exc_type', self.c_null_etype, llops)
excblock.operations[:] = llops
newgraph.exceptblock.inputargs[0].concretetype = self.lltype_of_exception_type
newgraph.exceptblock.inputargs[1].concretetype = self.lltype_of_exception_value
@@ -329,7 +335,7 @@
var_exc_occured = llops.genop('ptr_iszero', [spaceop.result],
lltype.Bool)
else:
- v_exc_type = self.ExcData_repr.getfield(self.cexcdata, 'exc_type', llops)
+ v_exc_type = self.gen_getfield('exc_type', llops)
var_exc_occured = llops.genop('ptr_nonzero', [v_exc_type],
lltype.Bool)
@@ -376,7 +382,6 @@
if normalafterblock is None:
normalafterblock = insert_empty_block(None, l0)
llops = rtyper.LowLevelOpList(None)
- r = self.ExcData_repr
- r.setfield(self.cexcdata, 'exc_value', self.c_null_evalue, llops)
- r.setfield(self.cexcdata, 'exc_type', self.c_null_etype, llops)
+ self.gen_setfield('exc_value', self.c_null_evalue, llops)
+ self.gen_setfield('exc_type', self.c_null_etype, llops)
normalafterblock.operations[:0] = llops
More information about the Pypy-commit
mailing list