[pypy-svn] r31972 - in pypy/dist/pypy/jit: codegen codegen/i386 codegen/i386/test codegen/llgraph timeshifter timeshifter/test
arigo at codespeak.net
arigo at codespeak.net
Sun Sep 3 20:59:51 CEST 2006
Author: arigo
Date: Sun Sep 3 20:59:48 2006
New Revision: 31972
Modified:
pypy/dist/pypy/jit/codegen/i386/ri386genop.py
pypy/dist/pypy/jit/codegen/i386/test/test_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/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/timeshift.py
pypy/dist/pypy/jit/timeshifter/vlist.py
Log:
(pedronis, arigo)
Big Diff Of The Day. The rgenop interface is getting in a nice shape:
no more links, and no more geninputarg(). Back-end friendly.
ri386genop produces code that is a bit more reasonable now (e.g. it's no
longer 95% moves)...
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 Sun Sep 3 20:59:48 2006
@@ -1,7 +1,7 @@
from pypy.rpython.objectmodel import specialize
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.jit.codegen.i386.ri386 import *
-from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenLink
+from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenerator
from pypy.jit.codegen.model import GenVar, GenConst
from pypy.rpython import objectmodel
from pypy.rpython.annlowlevel import llhelper
@@ -12,19 +12,22 @@
class Var(GenVar):
def __init__(self, stackpos):
- # 'stackpos' is an index relative to the pushed arguments:
- # 0 = 1st arg,
- # 1 = 2nd arg,
- # ...
- # return address,
- # local var, ...
+ # 'stackpos' is an index relative to the pushed arguments
+ # (where N is the number of arguments of the function):
+ #
+ # 0 = last arg
+ # = ...
+ # N-1 = 1st arg
+ # N = return address
+ # N+1 = local var
+ # N+2 = ...
# ... <--- esp+4
# local var <--- esp
#
self.stackpos = stackpos
- def operand(self, block):
- return block.stack_access(self.stackpos)
+ def operand(self, builder):
+ return builder.stack_access(self.stackpos)
def __repr__(self):
return 'var@%d' % (self.stackpos,)
@@ -60,7 +63,7 @@
def __init__(self, value):
self.value = value
- def operand(self, block):
+ def operand(self, builder):
return imm(self.value)
@specialize.arg(1)
@@ -88,7 +91,7 @@
def __init__(self, addr):
self.addr = addr
- def operand(self, block):
+ def operand(self, builder):
return imm(llmemory.cast_adr_to_int(self.addr))
@specialize.arg(1)
@@ -107,23 +110,31 @@
class Block(CodeGenBlock):
- def __init__(self, rgenop, mc):
+
+ def __init__(self, startaddr, arg_positions, stackdepth):
+ self.startaddr = startaddr
+ self.arg_positions = arg_positions
+ self.stackdepth = stackdepth
+
+
+class Builder(CodeGenerator):
+
+ def __init__(self, rgenop, mc, stackdepth):
self.rgenop = rgenop
- self.argcount = 0
- self.stackdepth = 0
+ self.stackdepth = stackdepth
self.mc = mc
- self.startaddr = mc.tell()
- self.fixedposition = False
- def getstartaddr(self):
- self.fixedposition = True
- return self.startaddr
-
- def geninputarg(self, kind):
- res = Var(self.argcount)
- self.argcount += 1
- self.stackdepth += 1
- return res
+ def _write_prologue(self, sigtoken):
+ numargs = sigtoken # for now
+ #self.mc.BREAKPOINT()
+ return [Var(pos) for pos in range(numargs-1, -1, -1)]
+
+ def _close(self):
+ self.rgenop.close_mc(self.mc)
+ self.mc = None
+
+ def _fork(self):
+ return self.rgenop.openbuilder(self.stackdepth)
@specialize.arg(1)
def genop1(self, opname, gv_arg):
@@ -194,16 +205,44 @@
else:
return gv_x
- def close1(self):
- return Link(self)
+ def enter_next_block(self, kinds, args_gv):
+ arg_positions = []
+ seen = {}
+ for i in range(len(args_gv)):
+ gv = args_gv[i]
+ # turn constants into variables; also make copies of vars that
+ # are duplicate in args_gv
+ if not isinstance(gv, Var) or gv.stackpos in seen:
+ gv = args_gv[i] = self.returnvar(gv.operand(self))
+ # remember the var's position in the stack
+ arg_positions.append(gv.stackpos)
+ seen[gv.stackpos] = None
+ return Block(self.mc.tell(), arg_positions, self.stackdepth)
+
+ def jump_if_false(self, gv_condition):
+ targetbuilder = self._fork()
+ self.mc.CMP(gv_condition.operand(self), imm8(0))
+ self.mc.JE(rel32(targetbuilder.mc.tell()))
+ return targetbuilder
- def close2(self, gv_condition):
- false_block = self.rgenop.newblock()
- false_block.stackdepth = self.stackdepth
- # XXX what if gv_condition is a Const?
+ def jump_if_true(self, gv_condition):
+ targetbuilder = self._fork()
self.mc.CMP(gv_condition.operand(self), imm8(0))
- self.mc.JE(rel32(false_block.getstartaddr()))
- return Link(false_block), Link(self)
+ self.mc.JNE(rel32(targetbuilder.mc.tell()))
+ return targetbuilder
+
+ def finish_and_return(self, sigtoken, gv_returnvar):
+ numargs = sigtoken # for now
+ initialstackdepth = numargs + 1
+ self.mc.MOV(eax, gv_returnvar.operand(self))
+ self.mc.ADD(esp, imm(WORD * (self.stackdepth - initialstackdepth)))
+ self.mc.RET()
+ self._close()
+
+ def finish_and_goto(self, outputargs_gv, targetblock):
+ remap_stack_layout(self, outputargs_gv, targetblock)
+ self.mc.JMP(rel32(targetblock.startaddr))
+ self._close()
# ____________________________________________________________
@@ -357,78 +396,74 @@
# ____________________________________________________________
-class Link(CodeGenLink):
-
- def __init__(self, prevblock):
- self.prevblock = prevblock
-
- def closereturn(self, gv_result):
- block = self.prevblock
- block.mc.MOV(eax, gv_result.operand(block))
- block.mc.ADD(esp, imm(WORD * block.stackdepth))
- block.mc.RET()
- block.rgenop.close_mc(block.mc)
-
- def close(self, outputargs_gv, targetblock):
- block = self.prevblock
- N = len(outputargs_gv)
- if block.stackdepth < N:
- block.mc.SUB(esp, imm(WORD * (N - block.stackdepth)))
- block.stackdepth = N
+def remap_stack_layout(builder, outputargs_gv, targetblock):
+ N = targetblock.stackdepth
+ if builder.stackdepth < N:
+ builder.mc.SUB(esp, imm(WORD * (N - builder.stackdepth)))
+ builder.stackdepth = N
+
+ M = len(outputargs_gv)
+ arg_positions = targetblock.arg_positions
+ assert M == len(arg_positions)
+ targetlayout = [None] * N
+ srccount = [-N] * N
+ for i in range(M):
+ pos = arg_positions[i]
+ gv = outputargs_gv[i]
+ assert targetlayout[pos] is None
+ targetlayout[pos] = gv
+ srccount[pos] = 0
+ pending_dests = M
+ for i in range(M):
+ gv = outputargs_gv[i]
+ if isinstance(gv, Var):
+ p = gv.stackpos
+ if 0 <= p < N:
+ if p == i:
+ srccount[p] = -N # ignore 'v=v'
+ pending_dests -= 1
+ else:
+ srccount[p] += 1
- pending_dests = N
- srccount = [0] * N
+ while pending_dests:
+ progress = False
for i in range(N):
- gv = outputargs_gv[i]
- if isinstance(gv, Var):
- p = gv.stackpos
- if 0 <= p < N:
- if p == i:
- srccount[p] = -N # ignore 'v=v'
- pending_dests -= 1
- else:
- srccount[p] += 1
-
- while pending_dests:
- progress = False
+ if srccount[i] == 0:
+ srccount[i] = -1
+ pending_dests -= 1
+ gv_src = targetlayout[i]
+ if isinstance(gv_src, Var):
+ p = gv_src.stackpos
+ if 0 <= p < N:
+ srccount[p] -= 1
+ builder.mc.MOV(eax, gv_src.operand(builder))
+ builder.mc.MOV(builder.stack_access(i), eax)
+ progress = True
+ if not progress:
+ # we are left with only pure disjoint cycles; break them
for i in range(N):
- if srccount[i] == 0:
- srccount[i] = -1
- pending_dests -= 1
- gv_src = outputargs_gv[i]
- if isinstance(gv_src, Var):
- p = gv_src.stackpos
- if 0 <= p < N:
- srccount[p] -= 1
- block.mc.MOV(eax, gv_src.operand(block))
- block.mc.MOV(block.stack_access(i), eax)
- progress = True
- if not progress:
- # we are left with only pure disjoint cycles; break them
- for i in range(N):
- if srccount[i] >= 0:
- dst = i
- block.mc.MOV(edx, block.stack_access(dst))
- while True:
- assert srccount[dst] == 1
- srccount[dst] = -1
- pending_dests -= 1
- gv_src = outputargs_gv[dst]
- assert isinstance(gv_src, Var)
- src = gv_src.stackpos
- assert 0 <= src < N
- if src == i:
- break
- block.mc.MOV(eax, block.stack_access(src))
- block.mc.MOV(block.stack_access(dst), eax)
- dst = src
- block.mc.MOV(block.stack_access(dst), edx)
- assert pending_dests == 0
-
- if block.stackdepth > N:
- block.mc.ADD(esp, imm(WORD * (block.stackdepth - N)))
- block.stackdepth = N
- block.rgenop.close_mc_and_jump(block.mc, targetblock)
+ if srccount[i] >= 0:
+ dst = i
+ builder.mc.MOV(edx, builder.stack_access(dst))
+ while True:
+ assert srccount[dst] == 1
+ srccount[dst] = -1
+ pending_dests -= 1
+ gv_src = targetlayout[dst]
+ assert isinstance(gv_src, Var)
+ src = gv_src.stackpos
+ assert 0 <= src < N
+ if src == i:
+ break
+ builder.mc.MOV(eax, builder.stack_access(src))
+ builder.mc.MOV(builder.stack_access(dst), eax)
+ dst = src
+ builder.mc.MOV(builder.stack_access(dst), edx)
+ assert pending_dests == 0
+
+ if builder.stackdepth > N:
+ builder.mc.ADD(esp, imm(WORD * (builder.stackdepth - N)))
+ builder.stackdepth = N
class RI386GenOp(AbstractRGenOp):
@@ -447,20 +482,16 @@
def close_mc(self, mc):
self.mcs.append(mc)
- def close_mc_and_jump(self, mc, targetblock):
- if (targetblock.fixedposition
- or targetblock.mc.tell() != targetblock.startaddr):
- mc.JMP(rel32(targetblock.getstartaddr()))
- self.close_mc(mc)
- else:
- # bring the targetblock here, instead of jumping to it
- self.close_mc(targetblock.mc)
- targetblock.mc = mc
- targetblock.startaddr = mc.tell()
- targetblock.fixedposition = True
+ def openbuilder(self, stackdepth):
+ return Builder(self, self.open_mc(), stackdepth)
- def newblock(self):
- return Block(self, self.open_mc())
+ def newgraph(self, sigtoken):
+ numargs = sigtoken # for now
+ initialstackdepth = numargs+1
+ builder = self.openbuilder(initialstackdepth)
+ entrypoint = builder.mc.tell()
+ inputargs_gv = builder._write_prologue(sigtoken)
+ return builder, entrypoint, inputargs_gv
@staticmethod
@specialize.genconst(0)
@@ -500,18 +531,10 @@
@staticmethod
@specialize.memo()
def sigToken(FUNCTYPE):
- return None # for now
+ return len(FUNCTYPE.ARGS) # for now
constPrebuiltGlobal = genconst
- def gencallableconst(self, sigtoken, name, block):
- prologue = self.newblock()
- #prologue.mc.BREAKPOINT()
- # re-push the arguments so that they are after the return value
- # and in the correct order
- for i in range(block.argcount):
- operand = mem(esp, WORD * (2*i+1))
- prologue.mc.PUSH(operand)
- self.close_mc_and_jump(prologue.mc, block)
- return IntConst(prologue.getstartaddr())
+ def gencallableconst(self, sigtoken, name, entrypointaddr):
+ return IntConst(entrypointaddr)
Modified: pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py (original)
+++ pypy/dist/pypy/jit/codegen/i386/test/test_ri386genop.py Sun Sep 3 20:59:48 2006
@@ -15,15 +15,11 @@
def make_adder(rgenop, n):
# 'return x+n'
- signed_kind = rgenop.kindToken(lltype.Signed)
- block = rgenop.newblock()
- gv_x = block.geninputarg(signed_kind)
- gv_result = block.genop2("int_add", gv_x, rgenop.genconst(n))
- link = block.close1()
- link.closereturn(gv_result)
-
sigtoken = rgenop.sigToken(FUNC)
- gv_add_one = rgenop.gencallableconst(sigtoken, "adder", block)
+ builder, entrypoint, [gv_x] = rgenop.newgraph(sigtoken)
+ gv_result = builder.genop2("int_add", gv_x, rgenop.genconst(n))
+ builder.finish_and_return(sigtoken, gv_result)
+ gv_add_one = rgenop.gencallableconst(sigtoken, "adder", entrypoint)
return gv_add_one
def runner(x, y):
@@ -62,25 +58,19 @@
def make_dummy(rgenop):
# 'return x - (y - (x-1))'
signed_kind = rgenop.kindToken(lltype.Signed)
- block = rgenop.newblock()
- gv_x = block.geninputarg(signed_kind)
- gv_y = block.geninputarg(signed_kind)
- gv_z = block.genop2("int_sub", gv_x, rgenop.genconst(1))
- link = block.close1()
-
- block2 = rgenop.newblock()
- gv_y2 = block2.geninputarg(signed_kind)
- gv_z2 = block2.geninputarg(signed_kind)
- gv_x2 = block2.geninputarg(signed_kind)
- link.close([gv_y, gv_z, gv_x], block2)
-
- gv_s2 = block2.genop2("int_sub", gv_y2, gv_z2)
- gv_t2 = block2.genop2("int_sub", gv_x2, gv_s2)
- link2 = block2.close1()
-
- link2.closereturn(gv_t2)
sigtoken = rgenop.sigToken(FUNC2)
- gv_dummyfn = rgenop.gencallableconst(sigtoken, "dummy", block)
+ builder, entrypoint, [gv_x, gv_y] = rgenop.newgraph(sigtoken)
+ gv_z = builder.genop2("int_sub", gv_x, rgenop.genconst(1))
+
+ args_gv = [gv_y, gv_z, gv_x]
+ builder.enter_next_block([signed_kind, signed_kind, signed_kind], args_gv)
+ [gv_y2, gv_z2, gv_x2] = args_gv
+
+ gv_s2 = builder.genop2("int_sub", gv_y2, gv_z2)
+ gv_t2 = builder.genop2("int_sub", gv_x2, gv_s2)
+ builder.finish_and_return(sigtoken, gv_t2)
+
+ gv_dummyfn = rgenop.gencallableconst(sigtoken, "dummy", entrypoint)
return gv_dummyfn
def dummy_runner(x, y):
@@ -118,27 +108,25 @@
# 'if x > 5: return x-1
# else: return y'
signed_kind = rgenop.kindToken(lltype.Signed)
- block = rgenop.newblock()
- gv_x = block.geninputarg(signed_kind)
- gv_y = block.geninputarg(signed_kind)
- gv_cond = block.genop2("int_gt", gv_x, rgenop.genconst(5))
- link_false, link_true = block.close2(gv_cond)
-
- block2 = rgenop.newblock()
- gv_one = block2.geninputarg(signed_kind)
- gv_x2 = block2.geninputarg(signed_kind)
- gv_y2 = block2.geninputarg(signed_kind)
- link_true.close([rgenop.genconst(1), gv_x, gv_y], block2)
-
- gv_s2 = block2.genop2("int_sub", gv_x2, gv_one)
- link2 = block2.close1()
- link2.closereturn(gv_s2)
+ sigtoken = rgenop.sigToken(FUNC2)
+ builder, entrypoint, [gv_x, gv_y] = rgenop.newgraph(sigtoken)
+ gv_cond = builder.genop2("int_gt", gv_x, rgenop.genconst(5))
+ false_builder = builder.jump_if_false(gv_cond)
+
+ # true path
+ args_gv = [rgenop.genconst(1), gv_x, gv_y]
+ builder.enter_next_block([signed_kind, signed_kind, signed_kind], args_gv)
+ [gv_one, gv_x2, gv_y2] = args_gv
- link_false.closereturn(gv_y)
+ gv_s2 = builder.genop2("int_sub", gv_x2, gv_one)
+ builder.finish_and_return(sigtoken, gv_s2)
- sigtoken = rgenop.sigToken(FUNC2)
+ # false path
+ false_builder.finish_and_return(sigtoken, gv_y)
+
+ # done
gv_branchingfn = rgenop.gencallableconst(sigtoken,
- "branching", block)
+ "branching", entrypoint)
return gv_branchingfn
def branching_runner(x, y):
@@ -175,3 +163,71 @@
assert res == 29
res = fn(3, 17)
assert res == 17
+
+# ____________________________________________________________
+
+def make_goto(rgenop):
+ # while x > 0:
+ # y += x
+ # x -= 1
+ # return y
+ signed_kind = rgenop.kindToken(lltype.Signed)
+ sigtoken = rgenop.sigToken(FUNC2)
+ builder, entrypoint, [gv_x, gv_y] = rgenop.newgraph(sigtoken)
+
+ # loop start block
+ args_gv = [gv_x, gv_y]
+ loopblock = builder.enter_next_block([signed_kind, signed_kind], args_gv)
+ [gv_x, gv_y] = args_gv
+
+ gv_cond = builder.genop2("int_gt", gv_x, rgenop.genconst(0))
+ bodybuilder = builder.jump_if_true(gv_cond)
+ builder.finish_and_return(sigtoken, gv_y)
+
+ # loop body
+ args_gv = [gv_y, gv_x]
+ bodybuilder.enter_next_block([signed_kind, signed_kind], args_gv)
+ [gv_y, gv_x] = args_gv
+
+ gv_y2 = bodybuilder.genop2("int_add", gv_x, gv_y)
+ gv_x2 = bodybuilder.genop2("int_sub", gv_x, rgenop.genconst(1))
+ bodybuilder.finish_and_goto([gv_x2, gv_y2], loopblock)
+
+ # done
+ gv_gotofn = rgenop.gencallableconst(sigtoken, "goto", entrypoint)
+ return gv_gotofn
+
+def goto_runner(x, y):
+ rgenop = RI386GenOp()
+ gv_gotofn = make_goto(rgenop)
+ gotofn = gv_gotofn.revealconst(lltype.Ptr(FUNC2))
+ res = gotofn(x, y)
+ keepalive_until_here(rgenop) # to keep the code blocks alive
+ return res
+
+def test_goto_interpret():
+ from pypy.jit.codegen.llgraph.rgenop import rgenop
+ gv_gotofn = make_goto(rgenop)
+ gotofn = gv_gotofn.revealconst(lltype.Ptr(FUNC2))
+ llinterp = LLInterpreter(None)
+ res = llinterp.eval_graph(gotofn._obj.graph, [30, 17])
+ assert res == 31 * 15 + 17
+ res = llinterp.eval_graph(gotofn._obj.graph, [3, 17])
+ assert res == 23
+
+def test_goto_direct():
+ rgenop = RI386GenOp()
+ gv_gotofn = make_goto(rgenop)
+ print gv_gotofn.value
+ fnptr = cast(c_void_p(gv_gotofn.value), CFUNCTYPE(c_int, c_int, c_int))
+ res = fnptr(30, 17) # <== the segfault is here
+ assert res == 31 * 15 + 17
+ res = fnptr(3, 17) # <== or here
+ assert res == 23
+
+def test_goto_compile():
+ fn = compile(goto_runner, [int, int], annotatorpolicy=GENOP_POLICY)
+ res = fn(30, 17)
+ assert res == 31 * 15 + 17
+ res = fn(3, 17)
+ assert res == 23
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 Sun Sep 3 20:59:48 2006
@@ -215,6 +215,7 @@
def _closelink(link, vars, targetblock):
if isinstance(link, flowmodel.Link):
+ assert link.target is None # link already closed
blockvars = dict.fromkeys(link.prevblock.getvariables())
for v in vars:
if isinstance(v, flowmodel.Variable):
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 Sun Sep 3 20:59:48 2006
@@ -1,6 +1,6 @@
from pypy.rpython.objectmodel import specialize
from pypy.rpython.lltypesystem import lltype
-from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenLink
+from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenerator
from pypy.jit.codegen.model import GenVar, GenConst
from pypy.jit.codegen.llgraph import llimpl
from pypy.rpython.lltypesystem.rclass import fishllattr
@@ -33,13 +33,11 @@
def __init__(self, b):
self.b = b
- def geninputarg(self, gv_TYPE):
- return LLVar(llimpl.geninputarg(self.b, gv_TYPE.v))
+class LLBuilder(CodeGenerator):
+ lnk = llimpl.nulllink
-## @specialize.arg(1)
-## def genop(self, opname, vars_gv, gv_RESULT_TYPE=None):
-## return LLVar(llimpl.genop(self.b, opname, vars_gv,
-## (gv_RESULT_TYPE or gv_Void).v))
+ def __init__(self):
+ self.rgenop = rgenop
@specialize.arg(1)
def genop1(self, opname, gv_arg):
@@ -100,36 +98,59 @@
def genop_same_as(self, gv_TYPE, gv_value):
return LLVar(gv_value.v)
- def close1(self):
- return LLLink(llimpl.closeblock1(self.b))
-
- def close2(self, gv_exitswitch):
- l1, l2 = llimpl.closeblock2(self.b, gv_exitswitch.v)
- return LLLink(l1), LLLink(l2)
-
-
-class LLLink(CodeGenLink):
- def __init__(self, l):
- self.l = l
-
- def close(self, vars_gv, targetblock):
- llimpl.closelink(self.l, vars_gv, targetblock.b)
-
- def closereturn(self, gv_returnvar):
- llimpl.closereturnlink(self.l,
+ def _newblock(self, kinds):
+ self.b = newb = llimpl.newblock()
+ return [LLVar(llimpl.geninputarg(newb, kind.v)) for kind in kinds]
+
+ def enter_next_block(self, kinds, args_gv):
+ lnk = self.lnk or llimpl.closeblock1(self.b)
+ self.lnk = llimpl.nulllink
+ newb_args_gv = self._newblock(kinds)
+ 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)
+
+ def finish_and_goto(self, args_gv, targetblock):
+ lnk = self.lnk or llimpl.closeblock1(self.b)
+ self.lnk = llimpl.nulllink
+ llimpl.closelink(lnk, args_gv, targetblock.b)
+
+ def finish_and_return(self, sigtoken, gv_returnvar):
+ lnk = self.lnk or llimpl.closeblock1(self.b)
+ self.lnk = llimpl.nulllink
+ llimpl.closereturnlink(lnk,
(gv_returnvar or gv_dummy_placeholder).v)
+ 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.lnk = l_true
+ self.lnk = l_false
+ return later_builder
+
+ 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.lnk = l_false
+ self.lnk = l_true
+ return later_builder
+
class RGenOp(AbstractRGenOp):
gv_Void = gv_Void
- def newblock(self):
- return LLBlock(llimpl.newblock())
- # XXX what kind of type/kind information does this need?
+ 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,
- targetblock):
- return LLConst(llimpl.gencallableconst(name, targetblock.b,
+ entrypoint):
+ return LLConst(llimpl.gencallableconst(name, entrypoint.b,
gv_FUNCTYPE.v))
@staticmethod
Modified: pypy/dist/pypy/jit/codegen/model.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/model.py (original)
+++ pypy/dist/pypy/jit/codegen/model.py Sun Sep 3 20:59:48 2006
@@ -10,10 +10,10 @@
is_const = True
-class CodeGenBlock(object):
+class CodeGenerator(object):
pass
-class CodeGenLink(object):
+class CodeGenBlock(object):
pass
Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Sun Sep 3 20:59:48 2006
@@ -170,12 +170,12 @@
for desc in typedesc.fielddescs]
#self.ownbox = ... set in ll_factory()
- def enter_block(self, newblock, incoming, memo):
+ def enter_block(self, incoming, memo):
contmemo = memo.containers
if self not in contmemo:
contmemo[self] = None
for box in self.content_boxes:
- box.enter_block(newblock, incoming, memo)
+ box.enter_block(incoming, memo)
def force_runtime_container(self, builder):
typedesc = self.typedesc
Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Sun Sep 3 20:59:48 2006
@@ -139,11 +139,10 @@
# ____________________________________________________________
# other jitstate/graph level operations
-def enter_graph(builder, backstate=None):
- return builder.build_jitstate(backstate)
+def enter_graph(backstate):
+ return JITState(backstate.curbuilder, backstate)
def start_new_block(states_dic, jitstate, key, redboxes):
- rgenop = jitstate.rgenop
memo = rvalue.freeze_memo()
frozens = [redbox.freeze(memo) for redbox in redboxes]
memo = rvalue.exactmatch_memo()
@@ -151,13 +150,16 @@
for i in range(len(redboxes)):
res = frozens[i].exactmatch(redboxes[i], outgoingvarboxes, memo)
assert res, "exactmatch() failed"
- newblock = rgenop.newblock()
linkargs = []
- for box in outgoingvarboxes:
- linkargs.append(box.getgenvar(None))
- box.genvar = newblock.geninputarg(box.kind)
- jitstate.curbuilder.enter_block(linkargs, newblock)
+ kinds = []
+ for box in outgoingvarboxes: # all variables
+ linkargs.append(box.genvar)
+ kinds.append(box.kind)
+ newblock = jitstate.curbuilder.enter_next_block(kinds, linkargs)
states_dic[key] = frozens, newblock
+ for i in range(len(outgoingvarboxes)):
+ box = outgoingvarboxes[i]
+ box.genvar = linkargs[i]
return jitstate
start_new_block._annspecialcase_ = "specialize:arglltype(2)"
@@ -178,18 +180,15 @@
exactmatch = False
if exactmatch:
- jitstate = dyn_enter_block(jitstate, outgoingvarboxes)
linkargs = []
for box in outgoingvarboxes:
linkargs.append(box.getgenvar(jitstate.curbuilder))
- jitstate.curbuilder.leave_block()
jitstate.curbuilder.finish_and_goto(linkargs, oldblock)
return None
# We need a more general block. Do it by generalizing all the
# redboxes from outgoingvarboxes, by making them variables.
# Then we make a new block based on this new state.
- jitstate = dyn_enter_block(jitstate, outgoingvarboxes)
replace_memo = rvalue.copy_memo()
for box in outgoingvarboxes:
box = box.forcevar(jitstate.curbuilder, replace_memo)
@@ -197,54 +196,45 @@
for i in range(len(mylocalredboxes)):
newbox = redboxes[i].replace(replace_memo)
mylocalredboxes[i] = redboxes[i] = newbox
- jitstate.curbuilder.leave_block()
return start_new_block(states_dic, jitstate, key, redboxes)
retrieve_jitstate_for_merge._annspecialcase_ = "specialize:arglltype(2)"
def enter_block(jitstate, redboxes):
# 'redboxes' is a fixed-size list (s_box_list) of the current red boxes
- rgenop = jitstate.rgenop
- newblock = rgenop.newblock()
- incoming = []
- memo = rvalue.enter_block_memo()
- for redbox in redboxes:
- redbox.enter_block(newblock, incoming, memo)
- js = jitstate.backstate
- while js is not None:
- lrb = js.localredboxes
- assert lrb is not None
- for redbox in lrb:
- redbox.enter_block(newblock, incoming, memo)
- js = js.backstate
- jitstate.curbuilder.enter_block(incoming, newblock)
- return jitstate
-
-def dyn_enter_block(jitstate, redboxes):
- # 'redboxes' is a var-sized list (s_box_accum) of *all* the boxes
- # including the ones from the callers' locals
- rgenop = jitstate.rgenop
- newblock = rgenop.newblock()
incoming = []
memo = rvalue.enter_block_memo()
for redbox in redboxes:
- redbox.enter_block(newblock, incoming, memo)
- jitstate.curbuilder.enter_block(incoming, newblock)
- return jitstate
-
-def leave_block(jitstate):
- jitstate.curbuilder.leave_block()
- return jitstate
+ redbox.enter_block(incoming, memo)
+## XXX
+## js = jitstate.backstate
+## while js is not None:
+## lrb = js.localredboxes
+## assert lrb is not None
+## for redbox in lrb:
+## redbox.enter_block(incoming, memo)
+## js = js.backstate
+ linkargs = []
+ kinds = []
+ for redbox in incoming: # all variables
+ linkargs.append(redbox.genvar)
+ kinds.append(redbox.kind)
+ jitstate.curbuilder.enter_next_block(kinds, linkargs)
+ for i in range(len(incoming)):
+ incoming[i].genvar = linkargs[i]
-def leave_block_split(jitstate, switchredbox, exitindex, redboxes):
+def leave_block_split(jitstate, switchredbox, exitindex,
+ redboxes_true, redboxes_false):
if switchredbox.is_constant():
- jitstate.curbuilder.leave_block()
return rvalue.ll_getvalue(switchredbox, lltype.Bool)
else:
exitgvar = switchredbox.getgenvar(jitstate.curbuilder)
- later_builder = jitstate.curbuilder.leave_block_split(exitgvar)
+ later_builder = jitstate.curbuilder.jump_if_false(exitgvar)
memo = rvalue.copy_memo()
- redboxcopies = [redbox.copy(memo) for redbox in redboxes]
+ redboxcopies = [None] * len(redboxes_false)
+ for i in range(len(redboxes_false)):
+ redboxcopies[i] = redboxes_false[i].copy(memo)
jitstate.split_queue.append((exitindex, later_builder, redboxcopies))
+ enter_block(jitstate, redboxes_true)
return True
def dispatch_next(jitstate, outredboxes):
@@ -252,6 +242,7 @@
if split_queue:
exitindex, later_builder, redboxes = split_queue.pop()
jitstate.curbuilder = later_builder
+ enter_block(jitstate, redboxes)
for box in redboxes:
outredboxes.append(box)
return exitindex
@@ -263,15 +254,13 @@
def prepare_return(jitstate, cache, return_type):
for builder, retbox in jitstate.return_queue[:-1]:
- builder.leave_block()
jitstate.curbuilder = builder
- retrieve_jitstate_for_merge(cache, jitstate, (), [retbox])
+ res = retrieve_jitstate_for_merge(cache, jitstate, (), [retbox])
+ assert res is None
frozens, block = cache[()]
- _, returnbox = jitstate.return_queue[-1]
- rgenop = jitstate.rgenop
- builder = ResidualGraphBuilder(rgenop, block)
- builder.valuebox = returnbox
- return builder
+ builder, returnbox = jitstate.return_queue[-1]
+ jitstate.backstate.curbuilder = builder
+ return returnbox
def ll_gvar_from_redbox(jitstate, redbox):
return redbox.getgenvar(jitstate.curbuilder)
@@ -282,125 +271,11 @@
def save_locals(jitstate, redboxes):
jitstate.localredboxes = redboxes
-def before_call(jitstate):
- leave_block(jitstate)
- return jitstate.curbuilder
-
-def after_call(jitstate, newbuilder):
- jitstate.curbuilder = newbuilder
- return newbuilder.valuebox
-
# ____________________________________________________________
-class ResidualGraphBuilder(object):
- def __init__(self, rgenop, block=None, link=None):
- self.rgenop = rgenop
- self.block = block
- self.outgoinglink = link
- self.valuebox = None
-
- def genconst(self, llvalue):
- return self.rgenop.genconst(llvalue)
- genconst._annspecialcase_ = 'specialize:genconst(1)'
-
-## def genvoidconst(self, dummy):
-## return self.rgenop.placeholder(dummy)
-## genvoidconst._annspecialcase_ = 'specialize:arg(1)'
-
-## def genop(self, opname, args_gv, result_kind=None):
-## return self.block.genop(opname, args_gv, result_kind)
-## genop._annspecialcase_ = 'specialize:arg(1)'
-
- def genop1(self, opname, gv_arg):
- return self.block.genop1(opname, gv_arg)
- genop1._annspecialcase_ = 'specialize:arg(1)'
-
- def genop2(self, opname, gv_arg1, gv_arg2):
- return self.block.genop2(opname, gv_arg1, gv_arg2)
- genop2._annspecialcase_ = 'specialize:arg(1)'
-
- def genop_call(self, sigtoken, gv_callable, args_gv):
- return self.block.genop_call(sigtoken, gv_callable, args_gv)
-
- def genop_getfield(self, fieldtoken, gv_ptr):
- return self.block.genop_getfield(fieldtoken, gv_ptr)
-
- def genop_setfield(self, fieldtoken, gv_ptr, gv_value):
- return self.block.genop_setfield(fieldtoken, gv_ptr, gv_value)
-
- def genop_getsubstruct(self, fieldtoken, gv_ptr):
- return self.block.genop_getsubstruct(fieldtoken, gv_ptr)
-
- def genop_getarrayitem(self, arraytoken, gv_ptr, gv_index):
- return self.block.genop_getarrayitem(arraytoken, gv_ptr, gv_index)
-
- def genop_getarraysize(self, arraytoken, gv_ptr):
- return self.block.genop_getarraysize(arraytoken, gv_ptr)
-
- def genop_malloc_fixedsize(self, alloctoken):
- return self.block.genop_malloc_fixedsize(alloctoken)
-
- def genop_same_as(self, kind, gv_value):
- return self.block.genop_same_as(kind, gv_value)
-
- def constTYPE(self, T):
- return self.rgenop.constTYPE(T)
- constTYPE._annspecialcase_ = 'specialize:arg(1)'
-
- def build_jitstate(self, backstate=None):
- return JITState(self, backstate)
-
- def enter_block(self, linkargs, newblock):
- self.outgoinglink.close(linkargs, newblock)
- self.block = newblock
- self.outgoinglink = None
-
- def leave_block(self):
- self.outgoinglink = self.block.close1()
-
- def leave_block_split(self, exitgvar):
- false_link, true_link = self.block.close2(exitgvar)
- later_builder = ResidualGraphBuilder(self.rgenop, link=false_link)
- self.outgoinglink = true_link
- return later_builder
-
- def finish_and_goto(self, linkargs, targetblock):
- self.outgoinglink.close(linkargs, targetblock)
- self.outgoinglink = None
-
- def finish_and_return(self):
- gv_retval = self.valuebox.getgenvar(self)
- returnlink = self.block.close1()
- returnlink.closereturn(gv_retval)
-
-def make_builder(rgenop):
- return ResidualGraphBuilder(rgenop, rgenop.newblock())
-
-def ll_int_box(kind, gv):
- return rvalue.IntRedBox(kind, gv)
-
-def ll_double_box(kind, gv):
- return rvalue.DoubleRedBox(kind, gv)
-
-def ll_addr_box(kind, gv):
- return rvalue.PtrRedBox(kind, gv)
-
-def ll_geninputarg(builder, kind):
- return builder.block.geninputarg(kind)
-
-def ll_end_setup_builder(builder):
- builder.leave_block()
- return builder.block
-
-def ll_close_builder(builder):
- builder.finish_and_return()
-
-def ll_gencallableconst(builder, name, startblock, gv_functype):
- return builder.rgenop.gencallableconst(name, startblock, gv_functype)
-
class JITState(object):
# XXX obscure interface
- localredboxes = None
+ localredboxes = []
def __init__(self, builder, backstate=None):
self.split_queue = []
Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtyper.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rtyper.py Sun Sep 3 20:59:48 2006
@@ -242,34 +242,24 @@
return v
else:
bk = self.annotator.bookkeeper
- # first close the current block
ts = self.timeshifter
v_jitstate = hop.llops.getjitstate()
- v_builder = hop.llops.genmixlevelhelpercall(rtimeshift.before_call,
- [ts.s_JITState],
- [v_jitstate],
- ts.s_ResidualGraphBuilder)
hop.r_s_popfirstarg()
args_hs = hop.args_s[:]
# fixed is always false here
graph = bk.get_graph_for_call(fnobj.graph, False, args_hs)
args_r = [self.getrepr(hs) for hs in args_hs]
args_v = hop.inputargs(*args_r)
- ARGS = [ts.r_ResidualGraphBuilder.lowleveltype,
- ts.r_JITState.lowleveltype]
+ ARGS = [ts.r_JITState.lowleveltype]
ARGS += [r.lowleveltype for r in args_r]
- RESULT = ts.r_ResidualGraphBuilder.lowleveltype
+ RESULT = ts.r_RedBox.lowleveltype
fnptr = lltype.functionptr(lltype.FuncType(ARGS, RESULT),
graph.name,
graph=graph,
_callable = graph.func)
self.timeshifter.schedule_graph(graph)
- args_v[:0] = [hop.llops.genconst(fnptr), v_builder, v_jitstate]
- v_newbuilder = hop.genop('direct_call', args_v, RESULT)
- return hop.llops.genmixlevelhelpercall(rtimeshift.after_call,
- [ts.s_JITState, ts.s_ResidualGraphBuilder],
- [v_jitstate, v_newbuilder],
- ts.s_RedBox)
+ args_v[:0] = [hop.llops.genconst(fnptr), v_jitstate]
+ return hop.genop('direct_call', args_v, RESULT)
def translate_op_save_locals(self, hop):
ts = self.timeshifter
Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rvalue.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rvalue.py Sun Sep 3 20:59:48 2006
@@ -38,12 +38,11 @@
def getgenvar(self, builder):
return self.genvar
- def enter_block(self, newblock, incoming, memo):
+ def enter_block(self, incoming, memo):
memo = memo.boxes
if not self.is_constant() and self not in memo:
- incoming.append(self.genvar)
+ incoming.append(self)
memo[self] = None
- self.genvar = newblock.geninputarg(self.kind)
def forcevar(self, builder, memo):
if self.is_constant():
@@ -212,11 +211,11 @@
assert self.genvar
return self.genvar
- def enter_block(self, newblock, incoming, memo):
+ def enter_block(self, incoming, memo):
if self.content:
- self.content.enter_block(newblock, incoming, memo)
+ self.content.enter_block(incoming, memo)
else:
- RedBox.enter_block(self, newblock, incoming, memo)
+ RedBox.enter_block(self, incoming, memo)
# ____________________________________________________________
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 Sun Sep 3 20:59:48 2006
@@ -5,9 +5,8 @@
from pypy.jit.hintannotator.model import *
from pypy.jit.timeshifter.timeshift import HintTimeshift
from pypy.jit.timeshifter import rtimeshift, rvalue, rtyper as hintrtyper
-from pypy.jit.llabstractinterp.test.test_llabstractinterp import annotation
-from pypy.jit.llabstractinterp.test.test_llabstractinterp import summary
-from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.objspace.flow.model import summary
+from pypy.rpython.lltypesystem import lltype, llmemory, rstr
from pypy.rpython.objectmodel import hint, keepalive_until_here
from pypy.rpython.unroll import unrolling_iterable
from pypy.rpython.annlowlevel import PseudoHighLevelCallable
@@ -26,6 +25,14 @@
def getargtypes(annotator, values):
return [annotation(annotator, x) for x in values]
+def annotation(a, x):
+ T = lltype.typeOf(x)
+ if T == lltype.Ptr(rstr.STR):
+ t = str
+ else:
+ t = annmodel.lltype_to_annotation(T)
+ return a.typeannotation(t)
+
def hannotate(func, values, policy=None, inline=None):
# build the normal ll graphs for ll_function
t = TranslationContext()
@@ -103,8 +110,8 @@
# (True=constant, False=variable) and a value
#
graph1 = ha.translator.graphs[0] # the timeshifted entry point
- assert len(graph1.getargs()) == 2 + len(values)
- graph1varargs = graph1.getargs()[2:]
+ assert len(graph1.getargs()) == 1 + len(values)
+ graph1varargs = graph1.getargs()[1:]
timeshifted_entrypoint_args_s = []
residual_argtypes = []
argcolors = []
@@ -131,16 +138,19 @@
graph1)
timeshifted_entrypoint = PseudoHighLevelCallable(
timeshifted_entrypoint_fnptr,
- [htshift.s_ResidualGraphBuilder, htshift.s_JITState]
+ [htshift.s_JITState]
+ timeshifted_entrypoint_args_s,
- htshift.s_ResidualGraphBuilder)
+ htshift.s_RedBox)
FUNC = lltype.FuncType(residual_argtypes, RESTYPE)
argcolors = unrolling_iterable(argcolors)
self.argcolors = argcolors
def ml_generate_code(rgenop, *args):
timeshifted_entrypoint_args = ()
- builder = rtimeshift.make_builder(rgenop)
+
+ sigtoken = rgenop.sigToken(FUNC)
+ builder, entrypoint, inputargs_gv = rgenop.newgraph(sigtoken)
+ i = 0
for color in argcolors:
if color == "green":
llvalue = args[0]
@@ -153,20 +163,24 @@
TYPE = lltype.typeOf(llvalue)
kind = rgenop.kindToken(TYPE)
boxcls = rvalue.ll_redboxcls(TYPE)
- gv_arg = rtimeshift.ll_geninputarg(builder, kind)
if is_constant:
- # ignore the gv_arg above, which is still present
+ # ignore the inputargs_gv[i], which is still present
# to give the residual graph a uniform signature
gv_arg = rgenop.genconst(llvalue)
+ else:
+ gv_arg = inputargs_gv[i]
box = boxcls(kind, gv_arg)
+ i += 1
timeshifted_entrypoint_args += (box,)
- startblock = rtimeshift.ll_end_setup_builder(builder)
- endbuilder = timeshifted_entrypoint(builder, None,
+
+ top_jitstate = rtimeshift.JITState(builder)
+ returnbox = timeshifted_entrypoint(top_jitstate,
*timeshifted_entrypoint_args)
- endbuilder.finish_and_return()
- sigtoken = rgenop.sigToken(FUNC)
+ gv_ret = returnbox.getgenvar(top_jitstate.curbuilder)
+ top_jitstate.curbuilder.finish_and_return(sigtoken, gv_ret)
+
gv_generated = rgenop.gencallableconst(sigtoken, "generated",
- startblock)
+ entrypoint)
generated = gv_generated.revealconst(lltype.Ptr(FUNC))
return generated
Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/timeshift.py (original)
+++ pypy/dist/pypy/jit/timeshifter/timeshift.py Sun Sep 3 20:59:48 2006
@@ -4,7 +4,7 @@
from pypy.annotation import model as annmodel
from pypy.annotation import listdef, dictdef
from pypy.jit.timeshifter import rvalue, oop
-from pypy.jit.timeshifter.rtimeshift import JITState, ResidualGraphBuilder
+from pypy.jit.timeshifter.rtimeshift import JITState
from pypy.rpython import rmodel, annlowlevel
from pypy.rpython.lltypesystem import rtuple, rlist, rdict
from pypy.jit.timeshifter import rtimeshift
@@ -26,7 +26,8 @@
self.latestexitindex = -1
self.annhelper = annlowlevel.MixLevelHelperAnnotator(rtyper)
- self.s_ResidualGraphBuilder, self.r_ResidualGraphBuilder = self.s_r_instanceof(ResidualGraphBuilder)
+ self.s_CodeGenerator, self.r_CodeGenerator = self.s_r_instanceof(
+ cgmodel.CodeGenerator)
self.s_JITState, self.r_JITState = self.s_r_instanceof(JITState)
self.s_RedBox, self.r_RedBox = self.s_r_instanceof(rvalue.RedBox)
self.s_OopSpecDesc, self.r_OopSpecDesc = self.s_r_instanceof(
@@ -38,63 +39,16 @@
getrepr = self.rtyper.getrepr
bk = rtyper.annotator.bookkeeper
- box_list_def = listdef.ListDef(None, self.s_RedBox)
- box_list_def.mutate()
+ box_list_def = listdef.ListDef(None, self.s_RedBox, mutated = True)
self.s_box_list = annmodel.SomeList(box_list_def)
self.r_box_list = getrepr(self.s_box_list)
self.r_box_list.setup()
- box_accum_def = listdef.ListDef(None, self.s_RedBox)
- box_accum_def.mutate()
- box_accum_def.resize()
+ box_accum_def = listdef.ListDef(None, self.s_RedBox, resized = True)
self.s_box_accum = annmodel.SomeList(box_accum_def)
self.r_box_accum = getrepr(self.s_box_accum)
self.r_box_accum.setup()
-## def ll_make_builder():
-## rgenop = RGenOp()
-## return rtimeshift.make_builder(rgenop)
-
-## # XXX find a different way to enforce the interface types
-## self.ll_make_builder_graph = self.annhelper.getgraph(
-## ll_make_builder,
-## [], self.s_ResidualGraphBuilder)
-## self.ll_int_box_graph = self.annhelper.getgraph(
-## rtimeshift.ll_int_box,
-## [self.s_ConstOrVar, self.s_ConstOrVar],
-## self.s_RedBox)
-## self.ll_addr_box_graph = self.annhelper.getgraph(
-## rtimeshift.ll_addr_box,
-## [self.s_ConstOrVar, self.s_ConstOrVar],
-## self.s_RedBox)
-## self.ll_double_box_graph = self.annhelper.getgraph(
-## rtimeshift.ll_int_box,
-## [self.s_ConstOrVar, self.s_ConstOrVar],
-## self.s_RedBox)
-## self.ll_geninputarg_graph = self.annhelper.getgraph(
-## rtimeshift.ll_geninputarg,
-## [self.s_ResidualGraphBuilder, self.s_ConstOrVar],
-## self.s_ConstOrVar)
-## self.ll_end_setup_builder_graph = self.annhelper.getgraph(
-## rtimeshift.ll_end_setup_builder,
-## [self.s_ResidualGraphBuilder],
-## self.s_Block)
-
-#### self.ll_close_jitstate_graph = self.annhelper.getgraph(
-#### rtimeshift.ll_close_jitstate,
-#### [self.s_JITState],
-#### annmodel.s_None)
-
-## self.ll_close_builder_graph = self.annhelper.getgraph(
-## rtimeshift.ll_close_builder,
-## [self.s_ResidualGraphBuilder],
-## annmodel.s_None)
-## self.annhelper.getgraph(
-## rtimeshift.ll_gencallableconst,
-## [self.s_ResidualGraphBuilder, annmodel.SomeString(),
-## self.s_Block, self.s_ConstOrVar],
-## self.s_ConstOrVar)
-
def s_r_instanceof(self, cls, can_be_None=True):
# Return a SomeInstance / InstanceRepr pair correspnding to the specified class.
return self.annhelper.s_r_instanceof(cls, can_be_None=can_be_None)
@@ -110,7 +64,7 @@
#
# then passes the variables to the target of link
#
- def getexitindex(self, link, inputargs, args_r, entering_links):
+ def getexitindex(self, link, entering_links):
self.latestexitindex += 1
v_jitstate = varoftype(self.r_JITState.lowleveltype, 'jitstate')
v_boxes = varoftype(self.r_box_accum.lowleveltype, 'boxes')
@@ -120,13 +74,14 @@
llops = HintLowLevelOpList(self, None)
reenter_vars = [v_jitstate]
+ i = 0
for var in link.args[1:]:
if isinstance(var, flowmodel.Constant):
reenter_vars.append(var)
continue
- i = inputargs.index(var)
- r = args_r[i]
+ r = self.hrtyper.bindingrepr(var)
v_box = self.read_out_box(llops, v_boxes, i)
+ i += 1
if isinstance(r, RedRepr):
reenter_vars.append(v_box)
else:
@@ -184,6 +139,10 @@
self.timeshift_block(timeshifted_blocks, entering_links, block)
originalblocks = timeshifted_blocks
+ inputlinkcounters = {}
+ for block in originalblocks:
+ inputlinkcounters[block] = len(entering_links[block])
+
returnblock = graph.returnblock
self.r_returnvalue = self.hrtyper.bindingrepr(returnblock.inputargs[0])
returnblock.operations = []
@@ -205,7 +164,7 @@
before_block = self.insert_before_block(block,
block_entering_links)
self.insert_bookkeeping_enter(block, before_block,
- len(block_entering_links))
+ inputlinkcounters[block])
self.insert_bookkeeping_leave_block(block, entering_links)
#self.hrtyper.insert_link_conversions(before_returnblock)
@@ -235,16 +194,15 @@
def insert_start_setup(self):
newstartblock = self.insert_before_block(self.graph.startblock, None, closeblock=True)
- v_builder = varoftype(self.r_ResidualGraphBuilder.lowleveltype, 'builder')
v_backstate = varoftype(self.r_JITState.lowleveltype, 'backstate')
v_jitstate = newstartblock.inputargs[0]
- newstartblock.inputargs[:1] = [v_builder, v_backstate]
+ newstartblock.inputargs[:1] = [v_backstate]
llops = HintLowLevelOpList(self, None)
llops.genop('direct_call', [self.c_ll_clearcaches_ptr])
v_jitstate1 = llops.genmixlevelhelpercall(rtimeshift.enter_graph,
- [self.s_ResidualGraphBuilder, self.s_JITState],
- [v_builder, v_backstate],
+ [self.s_JITState],
+ [v_backstate],
self.s_JITState)
llops.append(flowmodel.SpaceOperation('same_as', [v_jitstate1], v_jitstate))
newstartblock.operations = list(llops)
@@ -260,7 +218,7 @@
#elif len(link.args) == 1:
# assert False, "the return block should not be seen"
- def insert_before_block(self, block, entering_links, closeblock=True):
+ def insert_before_block(self, block, block_entering_links, closeblock=True):
newinputargs = [copyvar(self.hannotator, var) for var in block.inputargs]
newblock = flowmodel.Block(newinputargs)
@@ -269,7 +227,7 @@
newblock.isstartblock = True
self.graph.startblock = newblock
else:
- for link in entering_links:
+ for link in block_entering_links:
link.settarget(newblock)
if closeblock:
@@ -353,26 +311,9 @@
v_boxes = rlist.newlist(llops, self.r_box_list, type_erased_v)
return v_boxes
- # insert before non-join blocks a block with:
- #
- # newjitstate = rtimeshift.enter_block(jitstate, boxes)
- # where boxes = [current-redboxes]
- #
- # then pass the newjitstate (XXX modified?) and boxes
- # to the block original; boxes are modified in place
- #
+
def bookkeeping_enter_simple(self, args_r, newinputargs, before_block,
llops, v_boxes, is_returnblock=False):
- v_newjitstate = llops.genmixlevelhelpercall(rtimeshift.enter_block,
- [self.s_JITState, self.s_box_list],
- [newinputargs[0], v_boxes],
- self.s_JITState)
-
- bridge = before_block.exits[0]
- # not used any more: v_boxes is not modified by enter_block() nowadays
- #self.insert_read_out_boxes(bridge, llops, v_newjitstate, v_boxes, args_r, newinputargs)
- before_block.operations[:] = llops
-
return None
# insert before join blocks a block with:
@@ -492,126 +433,100 @@
return cache
- # insert after blocks the following logic:
- # if the original block is the returnblock:
+ # insert at the end of blocks the following logic:
+ # if the block is the returnblock:
#
# go to dispatch_block(jitstate)
#
- # if the original block has just one exit or the exitswitch is green:
+ # if the block has just one exit or the exitswitch is green:
#
- # newjitstate = rtimeshift.leave_block(jitstate)
+ # <nothing>
#
- # if the original block has more than one exit (split case):
+ # if the block has more than one exit (split case):
#
- # res = rtimeshift.leave_block_split(jitstate, exitswitchredbox, exitindex, boxes)
+ # res = rtimeshift.leave_block_split(jitstate,
+ # exitswitchredbox, exitindex,
+ # true_case_boxes,
+ # false_case_boxes)
# where
- # boxes =[boxes-for-all-current-red-and-green-values]
+ # true_case_boxes = [redboxes going into the true case link]
+ # false_case_boxes = [redbox going into the false case link
+ # + green values going into it wrapped into redboxes,
+ # all to be saved for later dispatch]
# exitindex = number identifying the false branch of the switch
# if res then go to true_exit_block
# else go to false_exit_block
#
# exitindex is computed by getexitindex, see comment for that method
#
- # leave_block_split if the exitswitchredbox is constant just returns its value as res
- # otherwise returns True and schedule the false case
+ # leave_block_split if the exitswitchredbox is constant just
+ # returns its value as res otherwise returns True
+ # and schedule the false case
#
def insert_bookkeeping_leave_block(self, block, entering_links):
- # XXX wrong with exceptions as much else
-
- renamemap = {}
- rename = lambda v: renamemap.get(v, v)
- inargs = []
-
- def introduce(v):
- if isinstance(v, flowmodel.Variable):
- if v not in renamemap:
- vprime = renamemap[v] = copyvar(self.hannotator, v)
- inargs.append(v)
-
- orig_v_jitstate = block.inputargs[0]
- introduce(orig_v_jitstate)
-
- newlinks = []
-
- v_newjitstate = varoftype(self.r_JITState.lowleveltype, 'jitstate')
- self.hannotator.bindings[v_newjitstate] = self.s_JITState
-
- def rename_on_link(v):
- if v is orig_v_jitstate:
- return v_newjitstate
- else:
- return rename(v)
+ exits = block.exits
+ exitswitch = block.exitswitch
- for link in block.exits:
- for v in link.args:
- introduce(v)
- newlink = link.copy(rename_on_link)
- newlink.llexitcase = newlink.exitcase # sanitize the link llexitcase
- newlinks.append(newlink)
- target = link.target
- # update entering_links as necessary
- if target in entering_links:
- target_entering_links = entering_links[target]
- target_entering_links.remove(link)
- target_entering_links.append(newlink)
- introduce(block.exitswitch)
-
- inputargs = [rename(v) for v in inargs]
- newblock = flowmodel.Block(inputargs)
- newblock.closeblock(*newlinks)
-
- inlink = flowmodel.Link(inargs, newblock)
- oldexitswitch = block.exitswitch
- block.exitswitch = None
- block.recloseblock(inlink)
-
- llops = HintLowLevelOpList(self, None)
- if len(newblock.exits) == 0: # this is the original returnblock
- newblock.recloseblock(flowmodel.Link(newblock.inputargs, self.dispatchblock))
- elif len(newblock.exits) == 1 or isinstance(self.hrtyper.bindingrepr(oldexitswitch), GreenRepr):
- newblock.exitswitch = rename(oldexitswitch)
- v_res = llops.genmixlevelhelpercall(rtimeshift.leave_block,
- [self.s_JITState],
- [rename(orig_v_jitstate)],
- self.s_JITState)
-
- llops.append(flowmodel.SpaceOperation('same_as',
- [v_res],
- v_newjitstate))
+ if len(exits) == 0: # this is the original returnblock
+ block.recloseblock(flowmodel.Link(block.inputargs[:1],
+ self.dispatchblock))
+ elif (len(exits) == 1 or
+ isinstance(self.hrtyper.bindingrepr(exitswitch), GreenRepr)):
+ pass # nothing to do
else:
- v_jitstate = rename(orig_v_jitstate)
- args_r = []
- boxes_v = []
- for var in inputargs[1:]:
- r = self.hrtyper.bindingrepr(var)
- args_r.append(r)
- if isinstance(r, RedRepr):
- boxes_v.append(var)
- elif isinstance(r, GreenRepr):
- v_box = self.make_const_box(llops, r, var, v_jitstate)
- boxes_v.append(v_box)
- else:
- raise RuntimeError('Unsupported boxtype')
-
- v_boxes = self.build_box_list(llops, boxes_v)
- false_exit = [exit for exit in newblock.exits if exit.exitcase is False][0]
- exitindex = self.getexitindex(false_exit, inputargs[1:], args_r, entering_links)
+ llops = HintLowLevelOpList(self, None)
+ v_jitstate = self.getjitstate(block)
+ assert len(exits) == 2
+ false_exit, true_exit = exits
+ if true_exit.exitcase is False:
+ true_exit, false_exit = false_exit, true_exit
+ assert true_exit.exitcase is True
+ assert false_exit.exitcase is False
+ # sanitize llexitcase
+ true_exit.llexitcase = True
+ false_exit.llexitcase = False
+ v_boxes_true = self.pack_state_into_boxes(llops,
+ true_exit.args[1:],
+ v_jitstate,
+ pack_greens_too=False)
+ v_boxes_false = self.pack_state_into_boxes(llops,
+ false_exit.args[1:],
+ v_jitstate,
+ pack_greens_too=True)
+ exitindex = self.getexitindex(false_exit, entering_links)
c_exitindex = rmodel.inputconst(lltype.Signed, exitindex)
v_res = llops.genmixlevelhelpercall(rtimeshift.leave_block_split,
[self.s_JITState,
self.s_RedBox,
annmodel.SomeInteger(),
+ self.s_box_list,
self.s_box_list],
[v_jitstate,
- rename(oldexitswitch),
+ exitswitch,
c_exitindex,
- v_boxes],
+ v_boxes_true,
+ v_boxes_false],
annmodel.SomeBool())
- llops.append(flowmodel.SpaceOperation('same_as',
- [inputargs[0]],
- v_newjitstate))
- newblock.exitswitch = v_res
- newblock.operations[:] = llops
+ block.exitswitch = v_res
+ block.operations.extend(llops)
+
+
+ def pack_state_into_boxes(self, llops, statevars, v_jitstate,
+ pack_greens_too):
+ boxes_v = []
+ for var in statevars:
+ if isinstance(var, flowmodel.Constant):
+ continue # it's correspondingly skipped in getexitindex()
+ r = self.hrtyper.bindingrepr(var)
+ if isinstance(r, RedRepr):
+ boxes_v.append(var)
+ elif isinstance(r, GreenRepr):
+ if pack_greens_too:
+ v_box = self.make_const_box(llops, r, var, v_jitstate)
+ boxes_v.append(v_box)
+ else:
+ raise RuntimeError('Unsupported boxtype')
+ return self.build_box_list(llops, boxes_v)
# put the following logic in the dispatch block:
#
@@ -626,13 +541,13 @@
#
# the prepare_return_block does:
#
- # builder = prepare_return(jitstate)
+ # returnbox = prepare_return(jitstate)
# where
# prepare_return = (lambda jitstate:
# rtimeshift.prepare_return(jitstate, return_cache,
# None))) # XXX return type info
# where return_cache is a predefined cache
- # return builder
+ # return returnbox
#
def insert_dispatch_logic(self):
dispatchblock = self.dispatchblock
@@ -640,8 +555,8 @@
llops = HintLowLevelOpList(self, None)
- v_returnbuilder = varoftype(self.r_ResidualGraphBuilder.lowleveltype, 'builder')
- returnblock = flowmodel.Block([v_returnbuilder])
+ v_returnbox = varoftype(self.r_RedBox.lowleveltype, 'returnbox')
+ returnblock = flowmodel.Block([v_returnbox])
returnblock.operations = ()
self.graph.returnblock = returnblock
@@ -685,7 +600,7 @@
llops = HintLowLevelOpList(self, None)
v_return_builder = llops.genmixlevelhelpercall(prepare_return,
[self.s_JITState], [v_jitstate2],
- self.s_ResidualGraphBuilder)
+ self.s_RedBox)
prepare_return_block.operations = list(llops)
finishedlink = flowmodel.Link([v_return_builder], returnblock)
Modified: pypy/dist/pypy/jit/timeshifter/vlist.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/vlist.py (original)
+++ pypy/dist/pypy/jit/timeshifter/vlist.py Sun Sep 3 20:59:48 2006
@@ -75,19 +75,19 @@
self.item_boxes = [itembox] * length
# self.ownbox = ... set in factory()
- def enter_block(self, newblock, incoming, memo):
+ def enter_block(self, incoming, memo):
contmemo = memo.containers
if self not in contmemo:
contmemo[self] = None
for box in self.item_boxes:
- box.enter_block(newblock, incoming, memo)
+ box.enter_block(incoming, memo)
def force_runtime_container(self, builder):
typedesc = self.typedesc
boxes = self.item_boxes
self.item_boxes = None
- args_gv = [None, builder.genconst(len(boxes))]
+ args_gv = [None, builder.rgenop.genconst(len(boxes))]
gv_list = builder.genop_call(typedesc.tok_ll_newlist,
typedesc.gv_ll_newlist,
args_gv)
@@ -95,7 +95,7 @@
self.ownbox.content = None
for i in range(len(boxes)):
gv_item = boxes[i].getgenvar(builder)
- args_gv = [gv_list, builder.genconst(i), gv_item]
+ args_gv = [gv_list, builder.rgenop.genconst(i), gv_item]
builder.genop_call(typedesc.tok_ll_setitem_fast,
typedesc.gv_ll_setitem_fast,
args_gv)
More information about the Pypy-commit
mailing list