[pypy-svn] r32715 - in pypy/dist/pypy: annotation jit/codegen jit/codegen/i386 jit/codegen/llgraph jit/codegen/llgraph/test jit/hintannotator jit/timeshifter jit/timeshifter/test rpython rpython/lltypesystem tool
arigo at codespeak.net
arigo at codespeak.net
Thu Sep 28 20:10:24 CEST 2006
Author: arigo
Date: Thu Sep 28 20:10:20 2006
New Revision: 32715
Added:
pypy/dist/pypy/jit/codegen/llgraph/test/test_rgenop.py
- copied unchanged from r32711, pypy/branch/jit-promotion/pypy/jit/codegen/llgraph/test/test_rgenop.py
pypy/dist/pypy/jit/timeshifter/test/test_promotion.py
- copied unchanged from r32711, pypy/branch/jit-promotion/pypy/jit/timeshifter/test/test_promotion.py
Removed:
pypy/dist/pypy/jit/codegen/llgraph/test/test_llimpl.py
Modified:
pypy/dist/pypy/annotation/annrpython.py
pypy/dist/pypy/jit/codegen/i386/ri386genop.py
pypy/dist/pypy/jit/codegen/llgraph/llimpl.py
pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
pypy/dist/pypy/jit/codegen/model.py
pypy/dist/pypy/jit/hintannotator/model.py
pypy/dist/pypy/jit/timeshifter/rcontainer.py
pypy/dist/pypy/jit/timeshifter/rtimeshift.py
pypy/dist/pypy/jit/timeshifter/rtyper.py
pypy/dist/pypy/jit/timeshifter/rvalue.py
pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
pypy/dist/pypy/jit/timeshifter/transform.py
pypy/dist/pypy/rpython/annlowlevel.py
pypy/dist/pypy/rpython/llinterp.py
pypy/dist/pypy/rpython/lltypesystem/lloperation.py
pypy/dist/pypy/tool/sourcetools.py
Log:
(pedronis, arre, arigo)
Merge the jit-promotion branch:
svn merge http://codespeak.net/svn/pypy/dist@32682
http://codespeak.net/svn/pypy/branch/jit-promotion
It adds "promotion": with x = hint(x, promote=True) we can force a red
variable to become green. This is implemented by pausing the
compilation and resuming it only when we get a run-time value arriving.
The "pause" contains run-time code that is a "flexible switch": a switch
where new cases can be added dynamically. The default case is the one
that calls back the compiler.
Modified: pypy/dist/pypy/annotation/annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/annrpython.py (original)
+++ pypy/dist/pypy/annotation/annrpython.py Thu Sep 28 20:10:20 2006
@@ -722,7 +722,8 @@
try:
resultcell = consider_meth(*argcells)
except Exception:
- raise_nicer_exception(op)
+ graph = self.bookkeeper.position_key[0]
+ raise_nicer_exception(op, str(graph))
if resultcell is None:
resultcell = annmodel.s_ImpossibleValue # no return value
elif resultcell == annmodel.s_ImpossibleValue:
Modified: pypy/dist/pypy/jit/codegen/i386/ri386genop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/ri386genop.py (original)
+++ pypy/dist/pypy/jit/codegen/i386/ri386genop.py Thu Sep 28 20:10:20 2006
@@ -436,8 +436,6 @@
return self.returnvar(eax)
op_uint_is_true = op_int_is_true
- op_uint_neg = op_int_neg
- op_uint_abs = identity
op_uint_invert = op_int_invert
op_uint_add = op_int_add
op_uint_sub = op_int_sub
Modified: pypy/dist/pypy/jit/codegen/llgraph/llimpl.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llgraph/llimpl.py (original)
+++ pypy/dist/pypy/jit/codegen/llgraph/llimpl.py Thu Sep 28 20:10:20 2006
@@ -23,16 +23,41 @@
c = from_opaque_object(gv_type)
return isinstance(c.value, lltype.Ptr)
-def initblock(opaqueptr):
- init_opaque_object(opaqueptr, flowmodel.Block([]))
-
def newblock():
- blockcontainer = lltype.malloc(BLOCKCONTAINERTYPE)
- initblock(blockcontainer.obj)
- return blockcontainer
+ block = flowmodel.Block([])
+ return to_opaque_object(block)
+
+def newgraph(gv_FUNCTYPE):
+ FUNCTYPE = from_opaque_object(gv_FUNCTYPE).value
+ inputargs = []
+ erasedinputargs = []
+ for ARG in FUNCTYPE.ARGS:
+ v = flowmodel.Variable()
+ v.concretetype = ARG
+ inputargs.append(v)
+ v = flowmodel.Variable()
+ v.concretetype = lltype.erasedType(ARG)
+ erasedinputargs.append(v)
+ startblock = flowmodel.Block(inputargs)
+ return_var = flowmodel.Variable()
+ return_var.concretetype = FUNCTYPE.RESULT
+ graph = flowmodel.FunctionGraph("in_progress", startblock, return_var)
+ v1 = flowmodel.Variable()
+ v1.concretetype = lltype.erasedType(FUNCTYPE.RESULT)
+ graph.prereturnblock = flowmodel.Block([v1])
+ casting_link(graph.prereturnblock, [v1], graph.returnblock)
+ substartblock = flowmodel.Block(erasedinputargs)
+ casting_link(graph.startblock, inputargs, substartblock)
+ return to_opaque_object(graph)
+
+def getstartblock(graph):
+ graph = from_opaque_object(graph)
+ [link] = graph.startblock.exits
+ substartblock = link.target
+ return to_opaque_object(substartblock)
-def geninputarg(blockcontainer, gv_CONCRETE_TYPE):
- block = from_opaque_object(blockcontainer.obj)
+def geninputarg(block, gv_CONCRETE_TYPE):
+ block = from_opaque_object(block)
assert not block.operations, "block already contains operations"
assert block.exits == [], "block already closed"
CONCRETE_TYPE = from_opaque_object(gv_CONCRETE_TYPE).value
@@ -41,6 +66,11 @@
block.inputargs.append(v)
return to_opaque_object(v)
+def getinputarg(block, i):
+ block = from_opaque_object(block)
+ v = block.inputargs[i]
+ return to_opaque_object(v)
+
def _inputvars(vars):
newvars = []
if not isinstance(vars, list):
@@ -67,12 +97,12 @@
res.append(v)
return res
-def cast(blockcontainer, gv_TYPE, gv_var):
+def cast(block, gv_TYPE, gv_var):
TYPE = from_opaque_object(gv_TYPE).value
v = from_opaque_object(gv_var)
if TYPE != v.concretetype:
assert v.concretetype == lltype.erasedType(TYPE)
- block = from_opaque_object(blockcontainer.obj)
+ block = from_opaque_object(block)
v2 = flowmodel.Variable()
v2.concretetype = TYPE
op = flowmodel.SpaceOperation('cast_pointer', [v], v2)
@@ -90,12 +120,12 @@
return v2
return v
-def genop(blockcontainer, opname, vars_gv, gv_RESULT_TYPE):
+def genop(block, opname, vars_gv, gv_RESULT_TYPE):
# 'opname' is a constant string
# gv_RESULT_TYPE comes from constTYPE
if not isinstance(opname, str):
opname = LLSupport.from_rstr(opname)
- block = from_opaque_object(blockcontainer.obj)
+ block = from_opaque_object(block)
assert block.exits == [], "block already closed"
opvars = _inputvars(vars_gv)
if gv_RESULT_TYPE is guess:
@@ -125,14 +155,15 @@
result = op.fold(*examples)
return lltype.typeOf(result)
-def gencallableconst(name, targetcontainer, gv_FUNCTYPE):
+def gencallableconst(name, graph, gv_FUNCTYPE):
# 'name' is just a way to track things
if not isinstance(name, str):
name = LLSupport.from_rstr(name)
- target = from_opaque_object(targetcontainer.obj)
+ graph = from_opaque_object(graph)
+ graph.name = name
FUNCTYPE = from_opaque_object(gv_FUNCTYPE).value
fptr = lltype.functionptr(FUNCTYPE, name,
- graph=_buildgraph(target, FUNCTYPE))
+ graph=_buildgraph(graph, FUNCTYPE))
return genconst(fptr)
def genconst(llvalue):
@@ -181,14 +212,14 @@
c.concretetype = lltype.Void
return to_opaque_object(c)
-def closeblock1(blockcontainer):
- block = from_opaque_object(blockcontainer.obj)
+def closeblock1(block):
+ block = from_opaque_object(block)
link = flowmodel.Link([], None)
block.closeblock(link)
return to_opaque_object(link)
-def closeblock2(blockcontainer, exitswitch):
- block = from_opaque_object(blockcontainer.obj)
+def closeblock2(block, exitswitch):
+ block = from_opaque_object(block)
exitswitch = from_opaque_object(exitswitch)
assert isinstance(exitswitch, flowmodel.Variable)
block.exitswitch = exitswitch
@@ -202,6 +233,29 @@
return pseudotuple(to_opaque_object(false_link),
to_opaque_object(true_link))
+def closeblockswitch(block, exitswitch):
+ block = from_opaque_object(block)
+ exitswitch = from_opaque_object(exitswitch)
+ assert isinstance(exitswitch, flowmodel.Variable)
+ block.exitswitch = exitswitch
+ default_link = flowmodel.Link([], None)
+ default_link.exitcase = "default"
+ default_link.llexitcase = None
+ block.closeblock(default_link)
+ return to_opaque_object(default_link)
+
+def add_case(block, exitcase):
+ block = from_opaque_object(block)
+ exitcase = from_opaque_object(exitcase)
+ assert isinstance(exitcase, flowmodel.Constant)
+ assert isinstance(block.exitswitch, flowmodel.Variable)
+ case_link = flowmodel.Link([], None)
+ case_link.exitcase = exitcase.value
+ case_link.llexitcase = exitcase.value
+ exits = block.exits[:-1] + (case_link,) + block.exits[-1:]
+ block.recloseblock(*exits)
+ return to_opaque_object(case_link)
+
class pseudotuple(object):
# something that looks both like a hl and a ll tuple
def __init__(self, *items):
@@ -233,84 +287,55 @@
else:
raise TypeError
-def closelink(link, vars, targetblockcontainer):
- link = from_opaque_object(link)
- targetblock = from_opaque_object(targetblockcontainer.obj)
- vars = _inputvars(vars)
- _closelink(link, vars, targetblock)
+def closelink(link, vars, targetblock):
+ try:
+ link = from_opaque_object(link)
+ targetblock = from_opaque_object(targetblock)
+ vars = _inputvars(vars)
+ _closelink(link, vars, targetblock)
+ except Exception, e:
+ import sys; tb = sys.exc_info()[2]
+ import pdb; pdb.post_mortem(tb)
+ raise
-def closereturnlink(link, returnvar):
+def closereturnlink(link, returnvar, graph):
returnvar = from_opaque_object(returnvar)
link = from_opaque_object(link)
- v = flowmodel.Variable()
- v.concretetype = returnvar.concretetype
- pseudoreturnblock = flowmodel.Block([v])
- pseudoreturnblock.operations = ()
- _closelink(link, [returnvar], pseudoreturnblock)
-
-def _patchgraph(graph, RESULT):
- returntype = None
- links = []
- for link in graph.iterlinks():
- if link.target.operations == ():
- assert len(link.args) == 1 # for now
- if returntype is None:
- returntype = link.target.inputargs[0].concretetype
- else:
- assert returntype == link.target.inputargs[0].concretetype
- links.append(link)
- if returntype is None:
- returntype = lltype.Void
- graph.returnblock.inputargs[0].concretetype = RESULT
- targetblock = casting_bridge([returntype], [RESULT], graph.returnblock)
- for link in links:
- link.target = targetblock
+ graph = from_opaque_object(graph)
+ _closelink(link, [returnvar], graph.prereturnblock)
+
+def casting_link(source, sourcevars, target):
+ assert len(sourcevars) == len(target.inputargs)
+ linkargs = []
+ for v, target_v in zip(sourcevars, target.inputargs):
+ if v.concretetype == target_v.concretetype:
+ linkargs.append(v)
+ else:
+ erasedv = flowmodel.Variable()
+ erasedv.concretetype = target_v.concretetype
+ source.operations.append(flowmodel.SpaceOperation('cast_pointer',
+ [v],
+ erasedv))
+ linkargs.append(erasedv)
+ source.closeblock(flowmodel.Link(linkargs, target))
+
+# ____________________________________________________________
class PseudoRTyper(object):
def __init__(self):
from pypy.rpython.typesystem import LowLevelTypeSystem
self.type_system = LowLevelTypeSystem.instance
-def casting_bridge(FROMS, TOS, target):
- if FROMS != TOS:
- operations = []
- inputargs = []
- linkargs = []
- for FROM, TO in zip(FROMS, TOS):
- v = flowmodel.Variable()
- v.concretetype = FROM
- inputargs.append(v)
- if FROM == TO:
- linkargs.append(v)
- else:
- erasedv = flowmodel.Variable()
- erasedv.concretetype = TO
- operations.append(flowmodel.SpaceOperation('cast_pointer',
- [v],
- erasedv))
- linkargs.append(erasedv)
- bridgeblock = flowmodel.Block(inputargs)
- bridgeblock.operations = operations
- bridge = flowmodel.Link(linkargs, target)
- bridgeblock.closeblock(bridge)
- return bridgeblock
- else:
- return target
-
-def _buildgraph(block, FUNCTYPE):
- ARGS = [v.concretetype for v in block.inputargs]
- startblock =casting_bridge(FUNCTYPE.ARGS, ARGS, block)
- graph = flowmodel.FunctionGraph('generated', startblock)
- _patchgraph(graph, FUNCTYPE.RESULT)
+def _buildgraph(graph, FUNCTYPE):
flowmodel.checkgraph(graph)
eliminate_empty_blocks(graph)
join_blocks(graph)
graph.rgenop = True
return graph
-def buildgraph(blockcontainer, FUNCTYPE):
- block = from_opaque_object(blockcontainer.obj)
- return _buildgraph(block, FUNCTYPE)
+def buildgraph(graph, FUNCTYPE):
+ graph = from_opaque_object(graph)
+ return _buildgraph(graph, FUNCTYPE)
def testgengraph(gengraph, args, viewbefore=False, executor=LLInterpreter):
if viewbefore:
@@ -318,32 +343,40 @@
llinterp = executor(PseudoRTyper())
return llinterp.eval_graph(gengraph, args)
-def runblock(blockcontainer, FUNCTYPE, args,
+def runblock(graph, FUNCTYPE, args,
viewbefore=False, executor=LLInterpreter):
- graph = buildgraph(blockcontainer, FUNCTYPE)
+ graph = buildgraph(graph, FUNCTYPE)
return testgengraph(graph, args, viewbefore, executor)
+def show_incremental_progress(graph):
+ from pypy import conftest
+ if conftest.option.view:
+ graph = from_opaque_object(graph)
+ graph.show()
+
# ____________________________________________________________
# RTyping of the above functions
-from pypy.rpython.extfunctable import declaretype, declareptrtype, declare
+from pypy.rpython.extfunctable import declareptrtype
-blocktypeinfo = declaretype(flowmodel.Block, "Block")
+blocktypeinfo = declareptrtype(flowmodel.Block, "Block")
consttypeinfo = declareptrtype(flowmodel.Constant, "ConstOrVar")
vartypeinfo = declareptrtype(flowmodel.Variable, "ConstOrVar")
vartypeinfo.set_lltype(consttypeinfo.get_lltype()) # force same lltype
linktypeinfo = declareptrtype(flowmodel.Link, "Link")
+graphtypeinfo = declareptrtype(flowmodel.FunctionGraph, "FunctionGraph")
CONSTORVAR = lltype.Ptr(consttypeinfo.get_lltype())
-BLOCKCONTAINERTYPE = blocktypeinfo.get_lltype()
-BLOCK = lltype.Ptr(BLOCKCONTAINERTYPE)
+BLOCK = lltype.Ptr(blocktypeinfo.get_lltype())
LINK = lltype.Ptr(linktypeinfo.get_lltype())
+GRAPH = lltype.Ptr(graphtypeinfo.get_lltype())
# support constants and types
nullvar = lltype.nullptr(CONSTORVAR.TO)
nullblock = lltype.nullptr(BLOCK.TO)
nulllink = lltype.nullptr(LINK.TO)
+nullgraph = lltype.nullptr(GRAPH.TO)
gv_Void = constTYPE(lltype.Void)
dummy_placeholder = placeholder(None)
@@ -384,9 +417,14 @@
s_ConstOrVar = annmodel.SomePtr(CONSTORVAR)#annmodel.SomeExternalObject(flowmodel.Variable)
s_Link = annmodel.SomePtr(LINK)#annmodel.SomeExternalObject(flowmodel.Link)
s_LinkPair = annmodel.SomeTuple([s_Link, s_Link])
+s_Block = annmodel.SomePtr(BLOCK)
+s_Graph = annmodel.SomePtr(GRAPH)
-setannotation(initblock, None)
+setannotation(newblock, s_Block)
+setannotation(newgraph, s_Graph)
+setannotation(getstartblock, s_Block)
setannotation(geninputarg, s_ConstOrVar)
+setannotation(getinputarg, s_ConstOrVar)
setannotation(genop, s_ConstOrVar)
setannotation(gencallableconst, s_ConstOrVar)
setannotation(genconst, s_ConstOrVar)
@@ -396,6 +434,8 @@
setannotation(isconst, annmodel.SomeBool())
setannotation(closeblock1, s_Link)
setannotation(closeblock2, s_LinkPair)
+setannotation(closeblockswitch, s_Link)
+setannotation(add_case, s_Link)
setannotation(closelink, None)
setannotation(closereturnlink, None)
@@ -405,3 +445,5 @@
setannotation(constFieldName, s_ConstOrVar, specialize_as_constant=True)
setannotation(constTYPE, s_ConstOrVar, specialize_as_constant=True)
#setannotation(placeholder, s_ConstOrVar, specialize_as_constant=True)
+
+setannotation(show_incremental_progress, None)
Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py (original)
+++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py Thu Sep 28 20:10:20 2006
@@ -1,7 +1,7 @@
from pypy.rpython.objectmodel import specialize
from pypy.rpython.lltypesystem import lltype
from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenerator
-from pypy.jit.codegen.model import GenVar, GenConst
+from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch
from pypy.jit.codegen.llgraph import llimpl
from pypy.rpython.lltypesystem.rclass import fishllattr
@@ -30,14 +30,29 @@
class LLBlock(CodeGenBlock):
- def __init__(self, b):
+ def __init__(self, b, g):
self.b = b
+ self.g = g
+
+class LLFlexSwitch(CodeGenSwitch):
+
+ def __init__(self, b, g):
+ self.b = b
+ self.g = g
+
+ def add_case(self, gv_case):
+ l_case = llimpl.add_case(self.b, gv_case.v)
+ builder = LLBuilder(self.g)
+ builder.lnk = l_case
+ return builder
+
class LLBuilder(CodeGenerator):
lnk = llimpl.nulllink
- def __init__(self):
+ def __init__(self, g):
self.rgenop = rgenop
+ self.g = g
@specialize.arg(1)
def genop1(self, opname, gv_arg):
@@ -114,7 +129,7 @@
llimpl.closelink(lnk, args_gv, self.b)
for i in range(len(args_gv)):
args_gv[i] = newb_args_gv[i]
- return LLBlock(self.b)
+ return LLBlock(self.b, self.g)
def finish_and_goto(self, args_gv, targetblock):
lnk = self.lnk or llimpl.closeblock1(self.b)
@@ -122,15 +137,15 @@
llimpl.closelink(lnk, args_gv, targetblock.b)
def finish_and_return(self, sigtoken, gv_returnvar):
+ gv_returnvar = gv_returnvar or gv_dummy_placeholder
lnk = self.lnk or llimpl.closeblock1(self.b)
self.lnk = llimpl.nulllink
- llimpl.closereturnlink(lnk,
- (gv_returnvar or gv_dummy_placeholder).v)
+ llimpl.closereturnlink(lnk, gv_returnvar.v, self.g)
def jump_if_true(self, gv_cond):
l_false, l_true = llimpl.closeblock2(self.b, gv_cond.v)
self.b = llimpl.nullblock
- later_builder = LLBuilder()
+ later_builder = LLBuilder(self.g)
later_builder.lnk = l_true
self.lnk = l_false
return later_builder
@@ -138,24 +153,36 @@
def jump_if_false(self, gv_cond):
l_false, l_true = llimpl.closeblock2(self.b, gv_cond.v)
self.b = llimpl.nullblock
- later_builder = LLBuilder()
+ later_builder = LLBuilder(self.g)
later_builder.lnk = l_false
self.lnk = l_true
return later_builder
+ def flexswitch(self, gv_switchvar):
+ l_default = llimpl.closeblockswitch(self.b, gv_switchvar.v)
+ flexswitch = LLFlexSwitch(self.b, self.g)
+ self.b = llimpl.nullblock
+ self.lnk = l_default
+ return flexswitch
+
+ def show_incremental_progress(self):
+ llimpl.show_incremental_progress(self.g)
+
class RGenOp(AbstractRGenOp):
gv_Void = gv_Void
def newgraph(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE)):
- builder = LLBuilder()
- inputargs_gv = builder._newblock(ARGS_gv)
- return builder, LLBlock(builder.b), inputargs_gv
-
- def gencallableconst(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE), name,
- entrypoint):
- return LLConst(llimpl.gencallableconst(name, entrypoint.b,
+ graph = llimpl.newgraph(gv_FUNCTYPE.v)
+ builder = LLBuilder(graph)
+ builder.b = llimpl.getstartblock(graph)
+ inputargs_gv = [LLVar(llimpl.getinputarg(builder.b, i))
+ for i in range(len(ARGS_gv))]
+ return builder, graph, inputargs_gv
+
+ def gencallableconst(self, (ARGS_gv, gv_RESULT, gv_FUNCTYPE), name, graph):
+ return LLConst(llimpl.gencallableconst(name, graph,
gv_FUNCTYPE.v))
@staticmethod
@@ -201,6 +228,15 @@
constPrebuiltGlobal = genconst
+ def replay(self, block, kinds):
+ builder = LLBuilder(block.g)
+ args_gv = builder._newblock(kinds)
+ return builder, args_gv
+
+ def stop_replay(self, endblock, kinds):
+ return [LLVar(llimpl.getinputarg(endblock.b, i))
+ for i in range(len(kinds))]
+
# not RPython, just for debugging. Specific to llgraph.
@staticmethod
def reveal(gv):
@@ -210,15 +246,6 @@
v = fishllattr(gv, 'v')
return llimpl.reveal(v)
- # Builds a real flow.model.FunctionGraph. Specific to llgraph.
- @staticmethod
- def buildgraph(block, FUNCTYPE):
- if hasattr(block, 'b'):
- b = block.b
- else:
- b = fishllattr(block, 'b')
- return llimpl.buildgraph(b, FUNCTYPE)
-
def _freeze_(self):
return True # no real point in using a full class in llgraph
Modified: pypy/dist/pypy/jit/codegen/model.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/model.py (original)
+++ pypy/dist/pypy/jit/codegen/model.py Thu Sep 28 20:10:20 2006
@@ -23,3 +23,7 @@
class AbstractRGenOp(object):
pass
+
+
+class CodeGenSwitch(object):
+ pass
Modified: pypy/dist/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/model.py (original)
+++ pypy/dist/pypy/jit/hintannotator/model.py Thu Sep 28 20:10:20 2006
@@ -258,6 +258,10 @@
# turn a variable to a constant
origin = getbookkeeper().myorigin()
return SomeLLAbstractConstant(hs_v1.concretetype, {origin: True})
+ if hs_flags.const.get('promote', False):
+ hs_concrete = SomeLLAbstractConstant(hs_v1.concretetype, {})
+ hs_concrete.eager_concrete = True
+ return hs_concrete
def getfield(hs_v1, hs_fieldname):
S = hs_v1.concretetype.TO
@@ -311,8 +315,6 @@
return hs_c1
def hint(hs_c1, hs_flags):
- if hs_flags.const.get('variable', False): # only for testing purposes!!!
- return SomeLLAbstractVariable(hs_c1.concretetype)
if hs_flags.const.get('concrete', False):
for o in hs_c1.origins:
o.set_fixed()
@@ -322,6 +324,7 @@
if hs_flags.const.get('forget', False):
assert isinstance(hs_c1, SomeLLAbstractConstant)
return reorigin(hs_c1)
+ return SomeLLAbstractValue.hint(hs_c1, hs_flags)
def direct_call(hs_f1, *args_hs):
bookkeeper = getbookkeeper()
Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Thu Sep 28 20:10:20 2006
@@ -1,5 +1,6 @@
import operator
from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.annlowlevel import cachedtype
from pypy.jit.timeshifter import rvalue
class AbstractContainer(object):
@@ -14,27 +15,8 @@
def op_getsubstruct(self, jitstate, fielddesc):
raise NotImplementedError
-
# ____________________________________________________________
-class cachedtype(type):
- """Metaclass for classes that should only have one instance per
- tuple of arguments given to the constructor."""
-
- def __init__(selfcls, name, bases, dict):
- super(cachedtype, selfcls).__init__(name, bases, dict)
- selfcls._instancecache = {}
-
- def __call__(selfcls, *args):
- d = selfcls._instancecache
- try:
- return d[args]
- except KeyError:
- instance = d[args] = selfcls.__new__(selfcls, *args)
- instance.__init__(*args)
- return instance
-
-
class StructTypeDesc(object):
__metaclass__ = cachedtype
firstsubstructdesc = None
Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Thu Sep 28 20:10:20 2006
@@ -1,8 +1,12 @@
import operator, weakref
+from pypy.annotation import model as annmodel
from pypy.rpython.lltypesystem import lltype, lloperation, llmemory
from pypy.jit.hintannotator.model import originalconcretetype
from pypy.jit.timeshifter import rvalue
from pypy.rpython.unroll import unrolling_iterable
+from pypy.rpython.annlowlevel import cachedtype, base_ptr_lltype
+from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
+from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
FOLDABLE_OPS = dict.fromkeys(lloperation.enum_foldable_ops())
@@ -184,7 +188,7 @@
incoming[i].genvar = linkargs[i]
return newblock
-def start_new_block(states_dic, jitstate, key):
+def start_new_block(states_dic, jitstate, key, global_resumer):
memo = rvalue.freeze_memo()
frozen = jitstate.freeze(memo)
memo = rvalue.exactmatch_memo()
@@ -193,11 +197,17 @@
assert res, "exactmatch() failed"
newblock = enter_next_block(jitstate, outgoingvarboxes)
states_dic[key] = frozen, newblock
+ if global_resumer:
+ greens_gv = jitstate.greens
+ rgenop = jitstate.curbuilder.rgenop
+ jitstate.promotion_path = PromotionPathRoot(greens_gv, rgenop,
+ frozen, newblock,
+ global_resumer)
start_new_block._annspecialcase_ = "specialize:arglltype(2)"
-def retrieve_jitstate_for_merge(states_dic, jitstate, key):
+def retrieve_jitstate_for_merge(states_dic, jitstate, key, global_resumer):
if key not in states_dic:
- start_new_block(states_dic, jitstate, key)
+ start_new_block(states_dic, jitstate, key, global_resumer)
return False # continue
frozen, oldblock = states_dic[key]
@@ -219,7 +229,7 @@
box.forcevar(jitstate.curbuilder, replace_memo)
if replace_memo.boxes:
jitstate.replace(replace_memo)
- start_new_block(states_dic, jitstate, key)
+ start_new_block(states_dic, jitstate, key, global_resumer)
return False # continue
retrieve_jitstate_for_merge._annspecialcase_ = "specialize:arglltype(2)"
@@ -231,8 +241,15 @@
def split(jitstate, switchredbox, resumepoint, *greens_gv):
exitgvar = switchredbox.getgenvar(jitstate.curbuilder)
- later_builder = jitstate.curbuilder.jump_if_false(exitgvar)
- jitstate.split(later_builder, resumepoint, list(greens_gv))
+ if exitgvar.is_const:
+ return exitgvar.revealconst(lltype.Bool)
+ else:
+ if jitstate.resuming is None:
+ later_builder = jitstate.curbuilder.jump_if_false(exitgvar)
+ jitstate.split(later_builder, resumepoint, list(greens_gv))
+ return True
+ else:
+ return jitstate.resuming.path.pop()
def collect_split(jitstate_chain, resumepoint, *greens_gv):
greens_gv = list(greens_gv)
@@ -304,6 +321,145 @@
##def ll_gvar_from_constant(jitstate, ll_value):
## return jitstate.curbuilder.rgenop.genconst(ll_value)
+
+
+class ResumingInfo(object):
+ def __init__(self, promotion_point, gv_value, path):
+ self.promotion_point = promotion_point
+ self.gv_value = gv_value
+ self.path = path
+
+class PromotionPoint(object):
+ def __init__(self, flexswitch, switchblock, promotion_path):
+ assert promotion_path is not None
+ self.flexswitch = flexswitch
+ self.switchblock = switchblock
+ self.promotion_path = promotion_path
+
+class AbstractPromotionPath(object):
+ pass
+
+class PromotionPathRoot(AbstractPromotionPath):
+ def __init__(self, greens_gv, rgenop, frozen, portalblock, global_resumer):
+ self.greens_gv = greens_gv
+ self.rgenop = rgenop
+ self.frozen = frozen
+ self.portalblock = portalblock
+ self.global_resumer = global_resumer
+
+ def follow_path(self, path):
+ return self
+
+ def continue_compilation(self, resuminginfo):
+ incoming = []
+ memo = rvalue.unfreeze_memo()
+ jitstate = self.frozen.unfreeze(incoming, memo)
+ kinds = [box.kind for box in incoming]
+ builder, vars_gv = self.rgenop.replay(self.portalblock, kinds)
+ for i in range(len(incoming)):
+ incoming[i].genvar = vars_gv[i]
+ jitstate.curbuilder = builder
+ jitstate.greens = self.greens_gv
+ jitstate.resuming = resuminginfo
+ assert jitstate.frame.backframe is None
+ self.global_resumer(jitstate)
+ builder.show_incremental_progress()
+
+class PromotionPathNode(AbstractPromotionPath):
+ def __init__(self, next):
+ self.next = next
+ def follow_path(self, path):
+ path.append(self.direct)
+ return self.next.follow_path(path)
+
+class PromotionPathDirect(PromotionPathNode):
+ direct = True
+
+class PromotionPathIndirect(PromotionPathNode):
+ direct = False
+
+def ll_continue_compilation(promotion_point_ptr, value):
+ try:
+ promotion_point = cast_base_ptr_to_instance(PromotionPoint,
+ promotion_point_ptr)
+ path = []
+ root = promotion_point.promotion_path.follow_path(path)
+ gv_value = root.rgenop.genconst(value)
+ resuminginfo = ResumingInfo(promotion_point, gv_value, path)
+ root.continue_compilation(resuminginfo)
+ except Exception, e:
+ lloperation.llop.debug_fatalerror(lltype.Void,
+ "compilation-time error", e)
+
+class PromotionDesc:
+ __metatype__ = cachedtype
+
+ def __init__(self, ERASED, hrtyper):
+## (s_PromotionPoint,
+## r_PromotionPoint) = hrtyper.s_r_instanceof(PromotionPoint)
+ fnptr = hrtyper.annhelper.delayedfunction(
+ ll_continue_compilation,
+ [annmodel.SomePtr(base_ptr_lltype()),
+ annmodel.lltype_to_annotation(ERASED)],
+ annmodel.s_None, needtype=True)
+ RGenOp = hrtyper.RGenOp
+ self.gv_continue_compilation = RGenOp.constPrebuiltGlobal(fnptr)
+ self.sigtoken = RGenOp.sigToken(lltype.typeOf(fnptr).TO)
+## self.PROMOTION_POINT = r_PromotionPoint.lowleveltype
+
+ def _freeze_(self):
+ return True
+
+def ll_promote(jitstate, box, promotiondesc):
+ builder = jitstate.curbuilder
+ gv_switchvar = box.getgenvar(builder)
+ if gv_switchvar.is_const:
+ return False
+ else:
+ incoming = []
+ memo = rvalue.enter_block_memo()
+ jitstate.enter_block(incoming, memo)
+ switchblock = enter_next_block(jitstate, incoming)
+
+ if jitstate.resuming is None:
+ gv_switchvar = box.genvar
+ flexswitch = builder.flexswitch(gv_switchvar)
+ # default case of the switch:
+ enter_block(jitstate)
+ pm = PromotionPoint(flexswitch, switchblock,
+ jitstate.promotion_path)
+ ll_pm = cast_instance_to_base_ptr(pm)
+ gv_pm = builder.rgenop.genconst(ll_pm)
+ gv_switchvar = box.genvar
+ builder.genop_call(promotiondesc.sigtoken,
+ promotiondesc.gv_continue_compilation,
+ [gv_pm, gv_switchvar])
+ linkargs = []
+ for box in incoming:
+ linkargs.append(box.getgenvar(builder))
+ builder.finish_and_goto(linkargs, switchblock)
+ return True
+ else:
+ assert jitstate.promotion_path is None
+ resuming = jitstate.resuming
+ assert len(resuming.path) == 0
+ pm = resuming.promotion_point
+
+ kinds = [box.kind for box in incoming]
+ vars_gv = jitstate.curbuilder.rgenop.stop_replay(pm.switchblock,
+ kinds)
+ for i in range(len(incoming)):
+ incoming[i].genvar = vars_gv[i]
+ box.genvar = resuming.gv_value
+
+ newbuilder = pm.flexswitch.add_case(resuming.gv_value)
+
+ jitstate.resuming = None
+ jitstate.promotion_path = pm.promotion_path
+ jitstate.curbuilder = newbuilder
+ enter_block(jitstate)
+ return False
+
# ____________________________________________________________
class BaseDispatchQueue(object):
@@ -346,6 +502,18 @@
assert vframe.backframe is None
return fullmatch
+ def unfreeze(self, incomingvarboxes, memo):
+ local_boxes = []
+ for fzbox in self.fz_local_boxes:
+ local_boxes.append(fzbox.unfreeze(incomingvarboxes, memo))
+ if self.fz_backframe is not None:
+ backframe = self.fz_backframe.unfreeze(incomingvarboxes, memo)
+ else:
+ backframe = None
+ vframe = VirtualFrame(backframe, BaseDispatchQueue())
+ vframe.local_boxes = local_boxes
+ return vframe
+
class FrozenJITState(object):
#fz_frame = ... set by freeze()
@@ -368,6 +536,12 @@
fullmatch = False
return fullmatch
+ def unfreeze(self, incomingvarboxes, memo):
+ frame = self.fz_frame .unfreeze(incomingvarboxes, memo)
+ exc_type_box = self.fz_exc_type_box .unfreeze(incomingvarboxes, memo)
+ exc_value_box = self.fz_exc_value_box.unfreeze(incomingvarboxes, memo)
+ return JITState(None, frame, exc_type_box, exc_value_box)
+
class VirtualFrame(object):
@@ -410,15 +584,17 @@
class JITState(object):
returnbox = None
next = None # for linked lists
+ resuming = None # or a ResumingInfo
def __init__(self, builder, frame, exc_type_box, exc_value_box,
- resumepoint=-1, newgreens=[]):
+ resumepoint=-1, newgreens=[], promotion_path=None):
self.curbuilder = builder
self.frame = frame
self.exc_type_box = exc_type_box
self.exc_value_box = exc_value_box
self.resumepoint = resumepoint
self.greens = newgreens
+ self.promotion_path = promotion_path
def split(self, newbuilder, newresumepoint, newgreens):
memo = rvalue.copy_memo()
@@ -427,7 +603,9 @@
self.exc_type_box .copy(memo),
self.exc_value_box.copy(memo),
newresumepoint,
- newgreens)
+ newgreens,
+ PromotionPathIndirect(self.promotion_path))
+ self.promotion_path = PromotionPathDirect(self.promotion_path)
# add the later_jitstate to the chain of pending-for-dispatch_next()
dispatch_queue = self.frame.dispatch_queue
later_jitstate.next = dispatch_queue.split_chain
@@ -456,6 +634,9 @@
enter_graph._annspecialcase_ = 'specialize:arg(1)'
# XXX is that too many specializations? ^^^
+class CompilationInterrupted(Exception):
+ pass
+
def merge_returning_jitstates(jitstate):
return_chain = jitstate.frame.dispatch_queue.return_chain
return_cache = {}
@@ -463,17 +644,18 @@
while return_chain is not None:
jitstate = return_chain
return_chain = return_chain.next
- res = retrieve_jitstate_for_merge(return_cache, jitstate, ())
+ res = retrieve_jitstate_for_merge(return_cache, jitstate, (), None)
if res is False: # not finished
jitstate.next = still_pending
still_pending = jitstate
- assert still_pending is not None
+ if still_pending is None:
+ raise CompilationInterrupted
most_general_jitstate = still_pending
still_pending = still_pending.next
while still_pending is not None:
jitstate = still_pending
still_pending = still_pending.next
- res = retrieve_jitstate_for_merge(return_cache, jitstate, ())
+ res = retrieve_jitstate_for_merge(return_cache, jitstate, (), None)
assert res is True # finished
return most_general_jitstate
Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtyper.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rtyper.py Thu Sep 28 20:10:20 2006
@@ -191,6 +191,14 @@
# the graph is transformed already
return self.annotator.bookkeeper.tsgraphsigs[tsgraph]
+ def get_residual_functype(self, tsgraph):
+ ha = self.annotator
+ args_hs, hs_res = self.get_sig_hs(ha.translator.graphs[0])
+ RESTYPE = originalconcretetype(hs_res)
+ ARGS = [originalconcretetype(hs_arg) for hs_arg in args_hs
+ if not hs_arg.is_green()]
+ return lltype.FuncType(ARGS, RESTYPE)
+
def make_new_lloplist(self, block):
return HintLowLevelOpList(self)
@@ -230,8 +238,11 @@
try:
return self.dispatchsubclasses[mergepointfamily]
except KeyError:
- attrnames = mergepointfamily.getattrnames()
- subclass = rtimeshift.build_dispatch_subclass(attrnames)
+ if mergepointfamily.is_global:
+ subclass = rtimeshift.BaseDispatchQueue
+ else:
+ attrnames = mergepointfamily.getattrnames()
+ subclass = rtimeshift.build_dispatch_subclass(attrnames)
self.dispatchsubclasses[mergepointfamily] = subclass
return subclass
@@ -357,24 +368,6 @@
[c_opdesc, v_jitstate] + args_v,
ts.s_RedBox)
- def translate_op_hint(self, hop):
- # don't try to generate hint operations, just discard them
- hints = hop.args_v[-1].value
- if hints.get('forget', False):
- T = originalconcretetype(hop.args_s[0])
- v_redbox = hop.inputarg(self.getredrepr(T), arg=0)
- assert isinstance(hop.r_result, GreenRepr)
- ts = self
- c_T = hop.inputconst(lltype.Void, T)
- s_T = ts.rtyper.annotator.bookkeeper.immutablevalue(T)
- s_res = annmodel.lltype_to_annotation(T)
- return hop.llops.genmixlevelhelpercall(rvalue.ll_getvalue,
- [ts.s_RedBox, s_T],
- [v_redbox, c_T],
- s_res)
-
- return hop.inputarg(hop.r_result, arg=0)
-
def translate_op_debug_log_exc(self, hop): # don't timeshift debug_log_exc
pass
@@ -717,8 +710,9 @@
args_s += [self.s_ConstOrVar] * len(greens_v)
args_v = [v_jitstate, v_switch, c_resumepoint]
args_v += greens_v
- hop.llops.genmixlevelhelpercall(rtimeshift.split, args_s, args_v,
- annmodel.s_None)
+ return hop.llops.genmixlevelhelpercall(rtimeshift.split,
+ args_s, args_v,
+ annmodel.SomeBool())
def translate_op_collect_split(self, hop):
GREENS = [v.concretetype for v in hop.args_v[1:]]
@@ -738,17 +732,25 @@
args_s, args_v,
annmodel.s_None)
- def translate_op_merge_point(self, hop):
+ def translate_op_merge_point(self, hop, global_resumer=None):
mpfamily = hop.args_v[0].value
attrname = hop.args_v[1].value
DispatchQueueSubclass = self.get_dispatch_subclass(mpfamily)
- def merge_point(jitstate, *key):
- dispatch_queue = jitstate.frame.dispatch_queue
- assert isinstance(dispatch_queue, DispatchQueueSubclass)
- states_dic = getattr(dispatch_queue, attrname)
- return rtimeshift.retrieve_jitstate_for_merge(states_dic,
- jitstate, key)
+ if mpfamily.is_global:
+ states_dic = {}
+ def merge_point(jitstate, *key):
+ return rtimeshift.retrieve_jitstate_for_merge(states_dic,
+ jitstate, key,
+ global_resumer)
+ else:
+ def merge_point(jitstate, *key):
+ dispatch_queue = jitstate.frame.dispatch_queue
+ assert isinstance(dispatch_queue, DispatchQueueSubclass)
+ states_dic = getattr(dispatch_queue, attrname)
+ return rtimeshift.retrieve_jitstate_for_merge(states_dic,
+ jitstate, key,
+ global_resumer)
greens_v = []
greens_s = []
@@ -767,6 +769,37 @@
[v_jitstate ] + greens_v,
annmodel.SomeBool())
+ def translate_op_global_merge_point(self, hop):
+ mpfamily = hop.args_v[0].value
+ attrname = hop.args_v[1].value
+ N = mpfamily.resumepoint_after_mergepoint[attrname]
+ tsgraph = mpfamily.tsgraph
+ ts_fnptr = self.gettscallable(tsgraph)
+ TS_FUNC = lltype.typeOf(ts_fnptr)
+ dummy_args = [ARG._defl() for ARG in TS_FUNC.TO.ARGS[1:]]
+ dummy_args = tuple(dummy_args)
+ JITSTATE = self.r_JITState.lowleveltype
+ RESIDUAL_FUNCTYPE = self.get_residual_functype(tsgraph)
+ residualSigToken = self.RGenOp.sigToken(RESIDUAL_FUNCTYPE)
+ ll_finish_jitstate = self.ll_finish_jitstate
+
+ args_s = [self.s_JITState] + [annmodel.lltype_to_annotation(ARG)
+ for ARG in TS_FUNC.TO.ARGS[1:]]
+ s_res = self.s_JITState
+ tsfn = annlowlevel.PseudoHighLevelCallable(ts_fnptr, args_s, s_res)
+
+ def call_for_global_resuming(jitstate):
+ jitstate.resumepoint = N
+ try:
+ finaljitstate = tsfn(jitstate, *dummy_args)
+ except rtimeshift.CompilationInterrupted:
+ pass
+ else:
+ ll_finish_jitstate(finaljitstate, residualSigToken)
+
+ return self.translate_op_merge_point(hop,
+ global_resumer = call_for_global_resuming)
+
def translate_op_save_return(self, hop):
v_jitstate = hop.llops.getjitstate()
return hop.llops.genmixlevelhelpercall(rtimeshift.save_return,
@@ -781,11 +814,29 @@
[v_jitstate ],
self.s_JITState)
hop.llops.setjitstate(v_newjs)
+
+ def translate_op_getresumepoint(self, hop):
+ v_jitstate = hop.llops.getjitstate()
return hop.llops.genmixlevelhelpercall(rtimeshift.getresumepoint,
[self.s_JITState],
- [v_newjs ],
+ [v_jitstate ],
annmodel.SomeInteger())
+ def translate_op_promote(self, hop):
+ TYPE = originalconcretetype(hop.args_s[0])
+ r_arg = self.getredrepr(TYPE)
+ [v_box] = hop.inputargs(r_arg)
+ r_result = self.getgreenrepr(TYPE)
+ ERASED = annmodel.annotation_to_lltype(r_result.erased_annotation())
+ desc = rtimeshift.PromotionDesc(ERASED, self)
+ s_desc = self.rtyper.annotator.bookkeeper.immutablevalue(desc)
+ c_desc = hop.inputconst(lltype.Void, desc)
+ v_jitstate = hop.llops.getjitstate()
+ return hop.llops.genmixlevelhelpercall(rtimeshift.ll_promote,
+ [self.s_JITState, self.s_RedBox, s_desc],
+ [v_jitstate , v_box , c_desc],
+ annmodel.SomeBool())
+
# handling of the various kinds of calls
def translate_op_oopspec_call(self, hop):
Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rvalue.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rvalue.py Thu Sep 28 20:10:20 2006
@@ -19,6 +19,9 @@
def copy_memo():
return Memo()
+def unfreeze_memo():
+ return Memo()
+
class RedBox(object):
__slots__ = ['kind', 'genvar']
@@ -135,9 +138,9 @@
return memo[self]
except KeyError:
if self.is_constant():
- result = FrozenIntConst(self.genvar)
+ result = FrozenIntConst(self.kind, self.genvar)
else:
- result = FrozenIntVar()
+ result = FrozenIntVar(self.kind)
memo[self] = result
return result
@@ -159,9 +162,9 @@
return memo[self]
except KeyError:
if self.is_constant():
- result = FrozenDoubleConst(self.genvar)
+ result = FrozenDoubleConst(self.kind, self.genvar)
else:
- result = FrozenDoubleVar()
+ result = FrozenDoubleVar(self.kind)
memo[self] = result
return result
@@ -205,14 +208,14 @@
return boxmemo[self]
except KeyError:
if self.content:
- result = FrozenPtrVirtual()
+ result = FrozenPtrVirtual(self.kind)
boxmemo[self] = result
result.fz_content = self.content.freeze(memo)
else:
if self.is_constant():
- result = FrozenPtrConst(self.genvar)
+ result = FrozenPtrConst(self.kind, self.genvar)
else:
- result = FrozenPtrVar()
+ result = FrozenPtrVar(self.kind)
boxmemo[self] = result
return result
@@ -234,11 +237,14 @@
class FrozenValue(object):
"""An abstract value frozen in a saved state.
"""
+ def __init__(self, kind):
+ self.kind = kind
class FrozenIntConst(FrozenValue):
- def __init__(self, gv_const):
+ def __init__(self, kind, gv_const):
+ self.kind = kind
self.gv_const = gv_const
def exactmatch(self, box, outgoingvarboxes, memo):
@@ -250,6 +256,10 @@
outgoingvarboxes.append(box)
return False
+ def unfreeze(self, incomingvarboxes, memo):
+ # XXX could return directly the original IntRedBox
+ return IntRedBox(self.kind, self.gv_const)
+
class FrozenIntVar(FrozenValue):
@@ -265,10 +275,21 @@
outgoingvarboxes.append(box)
return False
+ def unfreeze(self, incomingvarboxes, memo):
+ memo = memo.boxes
+ if self not in memo:
+ newbox = IntRedBox(self.kind, None)
+ incomingvarboxes.append(newbox)
+ memo[self] = newbox
+ return newbox
+ else:
+ return memo[self]
+
class FrozenDoubleConst(FrozenValue):
- def __init__(self, gv_const):
+ def __init__(self, kind, gv_const):
+ self.kind = kind
self.gv_const = gv_const
def exactmatch(self, box, outgoingvarboxes, memo):
@@ -280,6 +301,9 @@
outgoingvarboxes.append(box)
return False
+ def unfreeze(self, incomingvarboxes, memo):
+ return DoubleRedBox(self.kind, self.gv_const)
+
class FrozenDoubleVar(FrozenValue):
@@ -295,10 +319,21 @@
outgoingvarboxes.append(box)
return False
+ def unfreeze(self, incomingvarboxes, memo):
+ memo = memo.boxes
+ if self not in memo:
+ newbox = DoubleRedBox(self.kind, None)
+ incomingvarboxes.append(newbox)
+ memo[self] = newbox
+ return newbox
+ else:
+ return memo[self]
+
class FrozenPtrConst(FrozenValue):
- def __init__(self, gv_const):
+ def __init__(self, kind, gv_const):
+ self.kind = kind
self.gv_const = gv_const
def exactmatch(self, box, outgoingvarboxes, memo):
@@ -310,6 +345,9 @@
outgoingvarboxes.append(box)
return False
+ def unfreeze(self, incomingvarboxes, memo):
+ return PtrRedBox(self.kind, self.gv_const)
+
class FrozenPtrVar(FrozenValue):
@@ -325,6 +363,16 @@
outgoingvarboxes.append(box)
return False
+ def unfreeze(self, incomingvarboxes, memo):
+ memo = memo.boxes
+ if self not in memo:
+ newbox = PtrRedBox(self.kind, None)
+ incomingvarboxes.append(newbox)
+ memo[self] = newbox
+ return newbox
+ else:
+ return memo[self]
+
class FrozenPtrVirtual(FrozenValue):
@@ -336,3 +384,7 @@
else:
return self.fz_content.exactmatch(box.content, outgoingvarboxes,
memo)
+
+ def unfreeze(self, incomingvarboxes, memo):
+ #return self.fz_content.unfreeze(self.kind, incomingvarboxes, memo)
+ raise NotImplementedError
Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py (original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py Thu Sep 28 20:10:20 2006
@@ -99,8 +99,6 @@
fresh_jitstate = hrtyper.ll_fresh_jitstate
finish_jitstate = hrtyper.ll_finish_jitstate
- args_hs, hs_res = hrtyper.get_sig_hs(ha.translator.graphs[0])
- RESTYPE = originalconcretetype(hs_res)
t = rtyper.annotator.translator
for graph in ha.translator.graphs:
checkgraph(graph)
@@ -119,11 +117,10 @@
assert len(graph1.getargs()) == 1 + len(values)
graph1varargs = graph1.getargs()[1:]
timeshifted_entrypoint_args_s = []
- residual_argtypes = []
argcolors = []
generate_code_args_s = []
- for v, hs_arg, llvalue in zip(graph1varargs, args_hs, values):
+ for v, llvalue in zip(graph1varargs, values):
s_var = annmodel.ll_to_annotation(llvalue)
r = hrtyper.bindingrepr(v)
residual_v = r.residual_values(llvalue)
@@ -133,8 +130,6 @@
else:
color = "red"
assert residual_v == [llvalue], "XXX for now"
- ARGTYPE = originalconcretetype(hs_arg)
- residual_argtypes.append(ARGTYPE)
timeshifted_entrypoint_args_s.append(hrtyper.s_RedBox)
generate_code_args_s.append(annmodel.SomeBool())
argcolors.append(color)
@@ -147,7 +142,7 @@
[hrtyper.s_JITState]
+ timeshifted_entrypoint_args_s,
hrtyper.s_JITState)
- FUNC = lltype.FuncType(residual_argtypes, RESTYPE)
+ FUNC = hrtyper.get_residual_functype(ha.translator.graphs[0])
argcolors = unrolling_iterable(argcolors)
self.argcolors = argcolors
@@ -180,9 +175,13 @@
timeshifted_entrypoint_args += (box,)
top_jitstate = fresh_jitstate(builder)
- top_jitstate = timeshifted_entrypoint(top_jitstate,
+ try:
+ top_jitstate = timeshifted_entrypoint(top_jitstate,
*timeshifted_entrypoint_args)
- finish_jitstate(top_jitstate, sigtoken)
+ except rtimeshift.CompilationInterrupted:
+ pass
+ else:
+ finish_jitstate(top_jitstate, sigtoken)
gv_generated = rgenop.gencallableconst(sigtoken, "generated",
entrypoint)
@@ -272,9 +271,10 @@
# 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:
residual_graph.show()
- self.insns = summary(residual_graph)
if 'check_raises' not in kwds:
res = llinterp.eval_graph(residual_graph, residualargs)
@@ -314,6 +314,7 @@
return self.timeshift(ll_function, values, opt_consts, *args, **kwds)
def check_insns(self, expected=None, **counts):
+ self.insns = summary(self.residual_graph)
if expected is not None:
assert self.insns == expected
for opname, count in counts.items():
Modified: pypy/dist/pypy/jit/timeshifter/transform.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/transform.py (original)
+++ pypy/dist/pypy/jit/timeshifter/transform.py Thu Sep 28 20:10:20 2006
@@ -13,8 +13,11 @@
class MergePointFamily(object):
- def __init__(self):
+ def __init__(self, tsgraph, is_global=False):
+ self.tsgraph = tsgraph
+ self.is_global = is_global
self.count = 0
+ self.resumepoint_after_mergepoint = {}
def add(self):
result = self.count
self.count += 1
@@ -30,27 +33,32 @@
self.hannotator = hannotator
self.graph = graph
self.graphcolor = self.graph_calling_color(graph)
+ self.global_merge_points = self.graph_global_mps(self.graph)
self.resumepoints = {}
- self.mergepointfamily = MergePointFamily()
+ self.mergepoint_set = {} # set of blocks
+ self.mergepointfamily = MergePointFamily(graph,
+ self.global_merge_points)
self.c_mpfamily = inputconst(lltype.Void, self.mergepointfamily)
self.tsgraphs_seen = []
def transform(self):
- mergepoints = list(self.enumerate_merge_points())
+ self.compute_merge_points()
self.insert_save_return()
self.insert_splits()
- for block in mergepoints:
- self.insert_merge(block)
self.split_after_calls()
- self.insert_dispatcher()
+ self.handle_hints()
+ self.insert_merge_points()
self.insert_enter_graph()
+ self.insert_dispatcher()
self.insert_leave_graph()
- def enumerate_merge_points(self):
+ def compute_merge_points(self):
entrymap = mkentrymap(self.graph)
for block, links in entrymap.items():
if len(links) > 1 and block is not self.graph.returnblock:
- yield block
+ self.mergepoint_set[block] = True
+ if self.global_merge_points:
+ self.mergepoint_set[self.graph.startblock] = True
def graph_calling_color(self, tsgraph):
args_hs, hs_res = self.hannotator.bookkeeper.tsgraphsigs[tsgraph]
@@ -61,6 +69,12 @@
else:
return 'red'
+ def graph_global_mps(self, tsgraph):
+ try:
+ return tsgraph.func._global_merge_points_
+ except AttributeError:
+ return False
+
def timeshifted_graph_of(self, graph, args_v):
bk = self.hannotator.bookkeeper
args_hs = [self.hannotator.binding(v) for v in args_v]
@@ -147,6 +161,13 @@
reds.append(v)
return reds, greens
+ def before_start_block(self):
+ entryblock = self.new_block_before(self.graph.startblock)
+ entryblock.isstartblock = True
+ self.graph.startblock.isstartblock = False
+ self.graph.startblock = entryblock
+ return entryblock
+
def before_return_block(self):
block = self.graph.returnblock
block.operations = []
@@ -171,6 +192,7 @@
self.insert_split_handling(block)
def insert_split_handling(self, block):
+ # lots of clever in-line logic commented out
v_redswitch = block.exitswitch
link_f, link_t = block.exits
if link_f.exitcase:
@@ -178,35 +200,42 @@
assert link_f.exitcase is False
assert link_t.exitcase is True
- constant_block = Block([])
- nonconstant_block = Block([])
+## 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)
+## 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(nonconstant_block, 'save_locals', reds)
+ self.genop(block, 'save_locals', reds)
resumepoint = self.get_resume_point(link_f.target)
c_resumepoint = inputconst(lltype.Signed, resumepoint)
- self.genop(nonconstant_block, 'split',
- [v_redswitch, c_resumepoint] + greens)
+ v_flag = self.genop(block, 'split',
+ [v_redswitch, c_resumepoint] + 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(nonconstant_block, 'save_locals', reds)
- self.genop(nonconstant_block, 'enter_block', [])
- nonconstant_block.closeblock(Link(link_t.args, link_t.target))
-
- SSA_to_SSI({block : True, # reachable from outside
- constant_block : False,
- nonconstant_block: False}, self.hannotator)
+ 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:
@@ -239,6 +268,21 @@
def get_resume_point(self, block):
return self.get_resume_point_link(block).exitcase
+ def go_to_if(self, block, target, v_finished_flag):
+ block.exitswitch = v_finished_flag
+ [link_f] = block.exits
+ link_t = Link([self.c_dummy], target)
+ link_f.exitcase = False
+ link_t.exitcase = True
+ block.recloseblock(link_f, link_t)
+
+ def go_to_dispatcher_if(self, block, v_finished_flag):
+ self.go_to_if(block, self.graph.returnblock, v_finished_flag)
+
+ def insert_merge_points(self):
+ for block in self.mergepoint_set:
+ self.insert_merge(block)
+
def insert_merge(self, block):
reds, greens = self.sort_by_color(block.inputargs)
nextblock = self.naive_split_block(block, 0)
@@ -246,15 +290,15 @@
self.genop(block, 'save_locals', reds)
mp = self.mergepointfamily.add()
c_mp = inputconst(lltype.Void, mp)
- v_finished_flag = self.genop(block, 'merge_point',
+ if self.global_merge_points:
+ self.genop(block, 'save_greens', greens)
+ prefix = 'global_'
+ else:
+ prefix = ''
+ v_finished_flag = self.genop(block, '%smerge_point' % (prefix,),
[self.c_mpfamily, c_mp] + greens,
resulttype = lltype.Bool)
- block.exitswitch = v_finished_flag
- [link_f] = block.exits
- link_t = Link([self.c_dummy], self.graph.returnblock)
- link_f.exitcase = False
- link_t.exitcase = True
- block.recloseblock(link_f, link_t)
+ self.go_to_dispatcher_if(block, v_finished_flag)
restoreops = []
mapping = {}
@@ -269,10 +313,26 @@
SSA_to_SSI({block : True, # reachable from outside
nextblock: False}, self.hannotator)
+ if self.global_merge_points:
+ N = self.get_resume_point(nextblock)
+ self.mergepointfamily.resumepoint_after_mergepoint[mp] = N
+
def insert_dispatcher(self):
- if self.resumepoints:
+ if self.global_merge_points or self.resumepoints:
block = self.before_return_block()
- v_switchcase = self.genop(block, 'dispatch_next', [],
+ self.genop(block, 'dispatch_next', [])
+ if self.global_merge_points:
+ block = self.before_return_block()
+ entryblock = self.before_start_block()
+ v_rp = self.genop(entryblock, 'getresumepoint', [],
+ resulttype = lltype.Signed)
+ c_zero = inputconst(lltype.Signed, 0)
+ v_abnormal_entry = self.genop(entryblock, 'int_ge',
+ [v_rp, c_zero],
+ resulttype = lltype.Bool)
+ self.go_to_if(entryblock, block, v_abnormal_entry)
+
+ v_switchcase = self.genop(block, 'getresumepoint', [],
resulttype = lltype.Signed)
block.exitswitch = v_switchcase
defaultlink = block.exits[0]
@@ -297,11 +357,7 @@
self.genop(block, 'save_return', [])
def insert_enter_graph(self):
- entryblock = self.new_block_before(self.graph.startblock)
- entryblock.isstartblock = True
- self.graph.startblock.isstartblock = False
- self.graph.startblock = entryblock
-
+ entryblock = self.before_start_block()
self.genop(entryblock, 'enter_graph', [self.c_mpfamily])
def insert_leave_graph(self):
@@ -363,6 +419,11 @@
def make_call(self, block, op, save_locals_vars, color='red'):
self.genop(block, 'save_locals', save_locals_vars)
targets = dict(self.graphs_from(op))
+ for tsgraph in targets.values():
+ if self.graph_global_mps(tsgraph):
+ # make sure jitstate.resumepoint is set to zero
+ self.genop(block, 'resetresumepoint', [])
+ break
if len(targets) == 1:
[tsgraph] = targets.values()
c_tsgraph = inputconst(lltype.Void, tsgraph)
@@ -475,5 +536,53 @@
link.args = []
link.target = self.get_resume_point_link(nextblock).target
- self.insert_merge(nextblock) # to merge some of the possibly many
- # return jitstates
+ self.mergepoint_set[nextblock] = True # to merge some of the possibly
+ # many return jitstates
+
+ # __________ hints __________
+
+ def handle_hints(self):
+ for block in list(self.graph.iterblocks()):
+ for i in range(len(block.operations)-1, -1, -1):
+ op = block.operations[i]
+ if op.opname == 'hint':
+ hints = op.args[1].value
+ for key, value in hints.items():
+ if value == True:
+ methname = 'handle_%s_hint' % (key,)
+ if hasattr(self, methname):
+ handler = getattr(self, methname)
+ break
+ else:
+ handler = self.handle_default_hint
+ handler(block, i)
+
+ def handle_default_hint(self, block, i):
+ # just discard the hint by default
+ op = block.operations[i]
+ newop = SpaceOperation('same_as', [op.args[0]], op.result)
+ block.operations[i] = newop
+
+ def handle_forget_hint(self, block, i):
+ # a hint for testing only
+ op = block.operations[i]
+ assert self.hannotator.binding(op.result).is_green()
+ assert not self.hannotator.binding(op.args[0]).is_green()
+ newop = SpaceOperation('revealconst', [op.args[0]], op.result)
+ block.operations[i] = newop
+
+ def handle_promote_hint(self, block, i):
+ op = block.operations[i]
+ v_promote = op.args[0]
+ newop = SpaceOperation('revealconst', [v_promote], op.result)
+ block.operations[i] = newop
+
+ link = support.split_block_with_keepalive(block, i,
+ annotator=self.hannotator)
+ 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_promote],
+ resulttype = lltype.Bool)
+ self.go_to_dispatcher_if(block, v_finished_flag)
Modified: pypy/dist/pypy/rpython/annlowlevel.py
==============================================================================
--- pypy/dist/pypy/rpython/annlowlevel.py (original)
+++ pypy/dist/pypy/rpython/annlowlevel.py Thu Sep 28 20:10:20 2006
@@ -347,6 +347,7 @@
return annmodel.SomePtr(F)
def specialize_call(self, hop):
+ hop.exception_cannot_occur()
return hop.args_r[1].get_unique_llfn()
# ____________________________________________________________
@@ -372,6 +373,7 @@
def specialize_call(self, hop):
v_arg = hop.inputarg(hop.args_r[1], arg=1)
assert isinstance(v_arg.concretetype, lltype.Ptr)
+ hop.exception_cannot_occur()
return hop.genop('cast_pointer', [v_arg],
resulttype = hop.r_result.lowleveltype)
@@ -391,6 +393,7 @@
def specialize_call(self, hop):
v_arg = hop.inputarg(hop.args_r[1], arg=1)
assert isinstance(v_arg.concretetype, lltype.Ptr)
+ hop.exception_cannot_occur()
return hop.genop('cast_pointer', [v_arg],
resulttype = hop.r_result.lowleveltype)
@@ -409,11 +412,7 @@
## s_Instance, r_Instance = pol.annhelper.s_r_instanceof(s_Class.const)
## return annmodel.SomePtr(r_Instance.lowleveltype)
-## def specialize_call(self, hop):
-## v_arg = hop.inputarg(hop.args_r[1], arg=1)
-## assert isinstance(v_arg.concretetype, lltype.Ptr)
-## return hop.genop('cast_pointer', [v_arg],
-## resulttype = hop.r_result.lowleveltype)
+## ...
# ____________________________________________________________
Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py (original)
+++ pypy/dist/pypy/rpython/llinterp.py Thu Sep 28 20:10:20 2006
@@ -27,6 +27,10 @@
extra = ''
return '<LLException %r%s>' % (type_name(etype), extra)
+class LLFatalError(Exception):
+ def __str__(self):
+ return ': '.join([str(x) for x in self.args])
+
def type_name(etype):
if isinstance(lltype.typeOf(etype), lltype.Ptr):
return ''.join(etype.name).rstrip('\x00')
@@ -442,6 +446,14 @@
# do nothing, this is useful in compiled code
pass
+ def op_debug_fatalerror(self, ll_msg, ll_exc=None):
+ msg = ''.join(ll_msg.chars)
+ if ll_exc is None:
+ raise LLFatalError(msg)
+ else:
+ ll_exc_type = lltype.cast_pointer(rclass.OBJECTPTR, ll_exc).typeptr
+ raise LLFatalError(msg, LLException(ll_exc_type, ll_exc))
+
def op_keepalive(self, value):
pass
Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Thu Sep 28 20:10:20 2006
@@ -394,6 +394,7 @@
'debug_pdb': LLOp(),
'debug_log_exc': LLOp(),
'debug_assert': LLOp(canfold=True),
+ 'debug_fatalerror': LLOp(),
}
# __________ operations on PyObjects __________
Modified: pypy/dist/pypy/tool/sourcetools.py
==============================================================================
--- pypy/dist/pypy/tool/sourcetools.py (original)
+++ pypy/dist/pypy/tool/sourcetools.py Thu Sep 28 20:10:20 2006
@@ -109,6 +109,8 @@
src = inspect.getsource(object)
except IOError:
return None
+ except IndentationError:
+ return None
if hasattr(name, "__sourceargs__"):
return src % name.__sourceargs__
return src
More information about the Pypy-commit
mailing list