[pypy-svn] r31568 - in pypy/dist/pypy: annotation jit/codegen/i386 jit/codegen/i386/test jit/codegen/llgraph jit/llabstractinterp jit/timeshifter jit/timeshifter/test rpython rpython/lltypesystem rpython/test
arigo at codespeak.net
arigo at codespeak.net
Wed Aug 23 18:47:41 CEST 2006
Author: arigo
Date: Wed Aug 23 18:47:27 2006
New Revision: 31568
Removed:
pypy/dist/pypy/rpython/rgenop.py
pypy/dist/pypy/rpython/test/test_rgenop.py
Modified:
pypy/dist/pypy/annotation/bookkeeper.py
pypy/dist/pypy/annotation/policy.py
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/llabstractinterp/llabstractinterp.py
pypy/dist/pypy/jit/llabstractinterp/llcontainer.py
pypy/dist/pypy/jit/llabstractinterp/llvalue.py
pypy/dist/pypy/jit/timeshifter/oop.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/test/test_tl.py
pypy/dist/pypy/jit/timeshifter/test/test_tlr.py
pypy/dist/pypy/jit/timeshifter/test/test_vlist.py
pypy/dist/pypy/jit/timeshifter/timeshift.py
pypy/dist/pypy/jit/timeshifter/vlist.py
pypy/dist/pypy/rpython/annlowlevel.py
pypy/dist/pypy/rpython/lltypesystem/lltype.py
pypy/dist/pypy/rpython/lltypesystem/rclass.py
pypy/dist/pypy/rpython/lltypesystem/rlist.py
pypy/dist/pypy/rpython/rtyper.py
pypy/dist/pypy/rpython/test/test_rpbc.py
Log:
(pedronis, arigo)
Make the timeshifter parametrized on a RGenOp class, which is the
interface to specific code generation back-ends. For this we did the
following:
slightly change the interface of rgenop, which is now located in
pypy/jit/codegen/*/rgenop.py and is based on classes a bit more.
the old rgenop with opaque objects is located in codegen/llgraph/llimpl
and codegen/llgraph/rgenop gives a nicer OO interface over it.
updated codegen/i386/ri386genop to match the same OO interface.
fixed everything everywhere.
_annspecialcase_ = 'specialize:ll' can be used with any policy now.
added lltypesystem.rclass.fishllattr() to read an instance attribute
when we only have a low-level GcStruct. (Could be used to replace a few
existing 'inst_xyz' attribute fishing, too.)
Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py (original)
+++ pypy/dist/pypy/annotation/bookkeeper.py Wed Aug 23 18:47:27 2006
@@ -408,18 +408,16 @@
result.knowntype = tp # at least for types this needs to be correct
else:
result = SomePBC([self.getdesc(x)])
- elif hasattr(x, '__class__') \
- and x.__class__.__module__ != '__builtin__':
+ elif hasattr(x, '_freeze_') and x._freeze_():
# user-defined classes can define a method _freeze_(), which
# is called when a prebuilt instance is found. If the method
# returns True, the instance is considered immutable and becomes
# a SomePBC(). Otherwise it's just SomeInstance().
- frozen = hasattr(x, '_freeze_') and x._freeze_()
- if frozen:
- result = SomePBC([self.getdesc(x)])
- else:
- self.see_mutable(x)
- result = SomeInstance(self.getuniqueclassdef(x.__class__))
+ result = SomePBC([self.getdesc(x)])
+ elif hasattr(x, '__class__') \
+ and x.__class__.__module__ != '__builtin__':
+ self.see_mutable(x)
+ result = SomeInstance(self.getuniqueclassdef(x.__class__))
elif x is None:
return s_None
else:
@@ -512,18 +510,16 @@
result.knowntype = tp # at least for types this needs to be correct
else:
result = SomePBC([self.getdesc(x)])
- elif hasattr(x, '__class__') \
- and x.__class__.__module__ != '__builtin__':
+ elif hasattr(x, '_freeze_') and x._freeze_():
# user-defined classes can define a method _freeze_(), which
# is called when a prebuilt instance is found. If the method
# returns True, the instance is considered immutable and becomes
# a SomePBC(). Otherwise it's just SomeInstance().
- frozen = hasattr(x, '_freeze_') and x._freeze_()
- if frozen:
- result = SomePBC([self.getdesc(x)])
- else:
- self.see_mutable(x)
- result = SomeInstance(self.getuniqueclassdef(x.__class__))
+ result = SomePBC([self.getdesc(x)])
+ elif hasattr(x, '__class__') \
+ and x.__class__.__module__ != '__builtin__':
+ self.see_mutable(x)
+ result = SomeInstance(self.getuniqueclassdef(x.__class__))
elif x is None:
return s_None
else:
Modified: pypy/dist/pypy/annotation/policy.py
==============================================================================
--- pypy/dist/pypy/annotation/policy.py (original)
+++ pypy/dist/pypy/annotation/policy.py Wed Aug 23 18:47:27 2006
@@ -8,7 +8,7 @@
from pypy.annotation.bookkeeper import getbookkeeper
-class BasicAnnotatorPolicy:
+class BasicAnnotatorPolicy(object):
allow_someobjects = True
def event(pol, bookkeeper, what, *args):
@@ -83,6 +83,10 @@
specialize__argtype = staticmethod(specialize_argtype) # specialize:argtype(N)
specialize__arglistitemtype = staticmethod(specialize_arglistitemtype)
+ def specialize__ll(pol, *args):
+ from pypy.rpython.annlowlevel import LowLevelAnnotatorPolicy
+ return LowLevelAnnotatorPolicy.default_specialize(*args)
+
def override__ignore(pol, *args):
bk = getbookkeeper()
return bk.immutablevalue(None)
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 Wed Aug 23 18:47:27 2006
@@ -1,16 +1,14 @@
from pypy.rpython.lltypesystem import lltype
from pypy.jit.codegen.i386.codebuf import MachineCodeBlock
from pypy.jit.codegen.i386.ri386 import *
+from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenLink
+from pypy.jit.codegen.model import GenVar, GenConst
WORD = 4
-class VarOrConst(object):
- pass
-
-
-class Var(VarOrConst):
+class Var(GenVar):
def __init__(self, stackpos):
# 'stackpos' is an index relative to the pushed arguments:
@@ -28,13 +26,13 @@
return block.stack_access(self.stackpos)
-class TypeConst(VarOrConst):
+class TypeConst(GenConst):
def __init__(self, kind):
self.kind = kind
-class IntConst(VarOrConst):
+class IntConst(GenConst):
def __init__(self, value):
self.value = value
@@ -42,6 +40,10 @@
def operand(self, block):
return imm(self.value)
+ def revealconst(self, T):
+ return lltype.cast_int_to_ptr(T, self.value)
+ revealconst._annspecialcase_ = 'specialize:arg(1)'
+
class FnPtrConst(IntConst):
def __init__(self, value, mc):
@@ -49,8 +51,9 @@
self.mc = mc # to keep it alive
-class Block(object):
- def __init__(self, mc):
+class Block(CodeGenBlock):
+ def __init__(self, rgenop, mc):
+ self.rgenop = rgenop
self.argcount = 0
self.stackdepth = 0
self.mc = mc
@@ -62,6 +65,21 @@
self.stackdepth += 1
return res
+ def genop(self, opname, args_gv, gv_RESTYPE=None):
+ genmethod = getattr(self, 'op_' + opname)
+ return genmethod(args_gv, gv_RESTYPE)
+ genop._annspecialcase_ = 'specialize:arg(1)'
+
+ def close1(self):
+ return Link(self)
+
+ def close2(self, gv_condition):
+ false_block = self.rgenop.newblock()
+ false_block.stackdepth = self.stackdepth
+ self.mc.CMP(gv_condition.operand(self), imm8(0))
+ self.mc.JE(rel32(false_block.startaddr))
+ return Link(false_block), Link(self)
+
def stack_access(self, stackpos):
return mem(esp, WORD * (self.stackdepth-1 - stackpos))
@@ -89,51 +107,24 @@
return self.push(eax)
-class RI386GenOp(object):
- gv_IntWord = TypeConst('IntWord')
- gv_Void = TypeConst('Void')
+class Link(CodeGenLink):
- def __init__(self):
- self.mcs = [] # machine code blocks where no-one is currently writing
-
- def get_rgenop_for_testing():
- return RI386GenOp()
- get_rgenop_for_testing = staticmethod(get_rgenop_for_testing)
-
- def open_mc(self):
- if self.mcs:
- # XXX think about inserting NOPS for alignment
- return self.mcs.pop()
- else:
- return MachineCodeBlock(65536) # XXX supposed infinite for now
-
- def close_mc(self, mc):
- self.mcs.append(mc)
-
- def newblock(self):
- return Block(self.open_mc())
+ def __init__(self, prevblock):
+ self.prevblock = prevblock
- def closeblock1(self, block):
- return block # NB. links and blocks are the same for us
+ 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 closeblock2(self, block, gv_condition):
- false_block = self.newblock()
- false_block.stackdepth = block.stackdepth
- block.mc.CMP(gv_condition.operand(block), imm8(0))
- block.mc.JE(rel32(false_block.startaddr))
- return false_block, block
-
- def closereturnlink(self, link, gv_result):
- link.mc.MOV(eax, gv_result.operand(link))
- link.mc.ADD(esp, imm(WORD * link.stackdepth))
- link.mc.RET()
- self.close_mc(link.mc)
-
- def closelink(self, link, outputargs_gv, targetblock):
+ def close(self, outputargs_gv, targetblock):
+ block = self.prevblock
N = len(outputargs_gv)
- if link.stackdepth < N:
- link.mc.SUB(esp, imm(WORD * (N - link.stackdepth)))
- link.stackdepth = N
+ if block.stackdepth < N:
+ block.mc.SUB(esp, imm(WORD * (N - block.stackdepth)))
+ block.stackdepth = N
pending_dests = N
srccount = [0] * N
@@ -155,15 +146,15 @@
srccount[i] = -1
pending_dests -= 1
gv_src = outputargs_gv[i]
- link.mc.MOV(eax, gv_src.operand(link))
- link.mc.MOV(link.stack_access(i), eax)
+ 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
- link.mc.MOV(edx, link.stack_access(dst))
+ block.mc.MOV(edx, block.stack_access(dst))
while True:
assert srccount[dst] == 1
srccount[dst] = -1
@@ -174,20 +165,42 @@
assert 0 <= src < N
if src == i:
break
- link.mc.MOV(eax, link.stack_access(src))
- link.mc.MOV(link.stack_access(dst), eax)
+ block.mc.MOV(eax, block.stack_access(src))
+ block.mc.MOV(block.stack_access(dst), eax)
dst = src
- link.mc.MOV(link.stack_access(dst), edx)
+ block.mc.MOV(block.stack_access(dst), edx)
assert pending_dests == 0
- if link.stackdepth > N:
- link.mc.ADD(esp, imm(WORD * (link.stackdepth - N)))
- link.stackdepth = N
- link.mc.JMP(rel32(targetblock.startaddr))
- self.close_mc(link.mc)
+ if block.stackdepth > N:
+ block.mc.ADD(esp, imm(WORD * (block.stackdepth - N)))
+ block.stackdepth = N
+ block.mc.JMP(rel32(targetblock.startaddr))
+ block.rgenop.close_mc(block.mc)
+
+
+class RI386GenOp(AbstractRGenOp):
+ gv_IntWord = TypeConst('IntWord')
+ gv_Void = TypeConst('Void')
+
+ def __init__(self):
+ self.mcs = [] # machine code blocks where no-one is currently writing
+
+ def get_rgenop_for_testing():
+ return RI386GenOp()
+ get_rgenop_for_testing = staticmethod(get_rgenop_for_testing)
+
+ def open_mc(self):
+ if self.mcs:
+ # XXX think about inserting NOPS for alignment
+ return self.mcs.pop()
+ else:
+ return MachineCodeBlock(65536) # XXX supposed infinite for now
- def geninputarg(self, block, gv_TYPE):
- return block.geninputarg(gv_TYPE)
+ def close_mc(self, mc):
+ self.mcs.append(mc)
+
+ def newblock(self):
+ return Block(self, self.open_mc())
def genconst(llvalue):
T = lltype.typeOf(llvalue)
@@ -204,11 +217,6 @@
constTYPE._annspecialcase_ = 'specialize:memo'
constTYPE = staticmethod(constTYPE)
- def genop(self, block, opname, args_gv, gv_RESTYPE):
- genmethod = getattr(block, 'op_' + opname)
- return genmethod(args_gv, gv_RESTYPE)
- genop._annspecialcase_ = 'specialize:arg(2)'
-
def gencallableconst(self, name, block, gv_FUNCTYPE):
prologue = self.newblock()
#prologue.mc.BREAKPOINT()
@@ -220,9 +228,3 @@
prologue.mc.JMP(rel32(block.startaddr))
self.close_mc(prologue.mc)
return FnPtrConst(prologue.startaddr, prologue.mc)
-
- def revealconst(T, gv_const):
- assert isinstance(gv_const, IntConst) # for now
- return lltype.cast_int_to_ptr(T, gv_const.value)
- revealconst._annspecialcase_ = 'specialize:arg(0)'
- revealconst = staticmethod(revealconst)
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 Wed Aug 23 18:47:27 2006
@@ -14,12 +14,12 @@
# 'return x+n'
gv_SIGNED = rgenop.constTYPE(lltype.Signed)
block = rgenop.newblock()
- gv_x = rgenop.geninputarg(block, gv_SIGNED)
+ gv_x = block.geninputarg(gv_SIGNED)
args_gv = [gv_x,
rgenop.genconst(n)]
- gv_result = rgenop.genop(block, "int_add", args_gv, gv_SIGNED)
- link = rgenop.closeblock1(block)
- rgenop.closereturnlink(link, gv_result)
+ gv_result = block.genop("int_add", args_gv, gv_SIGNED)
+ link = block.close1()
+ link.closereturn(gv_result)
gv_FUNC = rgenop.constTYPE(FUNC)
gv_add_one = rgenop.gencallableconst("adder", block, gv_FUNC)
@@ -28,15 +28,15 @@
def runner(x, y):
rgenop = RI386GenOp()
gv_add_x = make_adder(rgenop, x)
- add_x = rgenop.revealconst(lltype.Ptr(FUNC), gv_add_x)
+ add_x = gv_add_x.revealconst(lltype.Ptr(FUNC))
res = add_x(y)
keepalive_until_here(rgenop) # to keep the code blocks alive
return res
def test_adder_interpret():
- from pypy.rpython import rgenop
+ from pypy.jit.codegen.llgraph.rgenop import rgenop
gv_add_5 = make_adder(rgenop, 5)
- add_5 = rgenop.revealconst(lltype.Ptr(FUNC), gv_add_5)
+ add_5 = gv_add_5.revealconst(lltype.Ptr(FUNC))
llinterp = LLInterpreter(None)
res = llinterp.eval_graph(add_5._obj.graph, [12])
assert res == 17
@@ -62,25 +62,25 @@
# 'return x - (y - (x-1))'
gv_SIGNED = rgenop.constTYPE(lltype.Signed)
block = rgenop.newblock()
- gv_x = rgenop.geninputarg(block, gv_SIGNED)
- gv_y = rgenop.geninputarg(block, gv_SIGNED)
+ gv_x = block.geninputarg(gv_SIGNED)
+ gv_y = block.geninputarg(gv_SIGNED)
args_gv = [gv_x, rgenop.genconst(1)]
- gv_z = rgenop.genop(block, "int_sub", args_gv, gv_SIGNED)
- link = rgenop.closeblock1(block)
+ gv_z = block.genop("int_sub", args_gv, gv_SIGNED)
+ link = block.close1()
block2 = rgenop.newblock()
- gv_y2 = rgenop.geninputarg(block2, gv_SIGNED)
- gv_z2 = rgenop.geninputarg(block2, gv_SIGNED)
- gv_x2 = rgenop.geninputarg(block2, gv_SIGNED)
- rgenop.closelink(link, [gv_y, gv_z, gv_x], block2)
+ gv_y2 = block2.geninputarg(gv_SIGNED)
+ gv_z2 = block2.geninputarg(gv_SIGNED)
+ gv_x2 = block2.geninputarg(gv_SIGNED)
+ link.close([gv_y, gv_z, gv_x], block2)
args_gv = [gv_y2, gv_z2]
- gv_s2 = rgenop.genop(block2, "int_sub", args_gv, gv_SIGNED)
+ gv_s2 = block2.genop("int_sub", args_gv, gv_SIGNED)
args_gv = [gv_x2, gv_s2]
- gv_t2 = rgenop.genop(block2, "int_sub", args_gv, gv_SIGNED)
- link2 = rgenop.closeblock1(block2)
+ gv_t2 = block2.genop("int_sub", args_gv, gv_SIGNED)
+ link2 = block2.close1()
- rgenop.closereturnlink(link2, gv_t2)
+ link2.closereturn(gv_t2)
gv_FUNC2 = rgenop.constTYPE(FUNC2)
gv_dummyfn = rgenop.gencallableconst("dummy", block, gv_FUNC2)
return gv_dummyfn
@@ -88,15 +88,15 @@
def dummy_runner(x, y):
rgenop = RI386GenOp()
gv_dummyfn = make_dummy(rgenop)
- dummyfn = rgenop.revealconst(lltype.Ptr(FUNC2), gv_dummyfn)
+ dummyfn = gv_dummyfn.revealconst(lltype.Ptr(FUNC2))
res = dummyfn(x, y)
keepalive_until_here(rgenop) # to keep the code blocks alive
return res
def test_dummy_interpret():
- from pypy.rpython import rgenop
+ from pypy.jit.codegen.llgraph.rgenop import rgenop
gv_dummyfn = make_dummy(rgenop)
- dummyfn = rgenop.revealconst(lltype.Ptr(FUNC2), gv_dummyfn)
+ dummyfn = gv_dummyfn.revealconst(lltype.Ptr(FUNC2))
llinterp = LLInterpreter(None)
res = llinterp.eval_graph(dummyfn._obj.graph, [30, 17])
assert res == 42
@@ -122,22 +122,22 @@
gv_SIGNED = rgenop.constTYPE(lltype.Signed)
gv_BOOL = rgenop.constTYPE(lltype.Bool)
block = rgenop.newblock()
- gv_x = rgenop.geninputarg(block, gv_SIGNED)
- gv_y = rgenop.geninputarg(block, gv_SIGNED)
+ gv_x = block.geninputarg(gv_SIGNED)
+ gv_y = block.geninputarg(gv_SIGNED)
args_gv = [gv_x, rgenop.genconst(5)]
- gv_cond = rgenop.genop(block, "int_gt", args_gv, gv_BOOL)
- link_false, link_true = rgenop.closeblock2(block, gv_cond)
+ gv_cond = block.genop("int_gt", args_gv, gv_BOOL)
+ link_false, link_true = block.close2(gv_cond)
block2 = rgenop.newblock()
- gv_x2 = rgenop.geninputarg(block2, gv_SIGNED)
- rgenop.closelink(link_true, [gv_x], block2)
+ gv_x2 = block2.geninputarg(gv_SIGNED)
+ link_true.close([gv_x], block2)
args_gv = [gv_x2, rgenop.genconst(1)]
- gv_s2 = rgenop.genop(block2, "int_sub", args_gv, gv_SIGNED)
- link2 = rgenop.closeblock1(block2)
- rgenop.closereturnlink(link2, gv_s2)
+ gv_s2 = block2.genop("int_sub", args_gv, gv_SIGNED)
+ link2 = block2.close1()
+ link2.closereturn(gv_s2)
- rgenop.closereturnlink(link_false, gv_y)
+ link_false.closereturn(gv_y)
gv_FUNC2 = rgenop.constTYPE(FUNC2)
gv_branchingfn = rgenop.gencallableconst("branching", block, gv_FUNC2)
@@ -146,15 +146,15 @@
def branching_runner(x, y):
rgenop = RI386GenOp()
gv_branchingfn = make_branching(rgenop)
- branchingfn = rgenop.revealconst(lltype.Ptr(FUNC2), gv_branchingfn)
+ branchingfn = gv_branchingfn.revealconst(lltype.Ptr(FUNC2))
res = branchingfn(x, y)
keepalive_until_here(rgenop) # to keep the code blocks alive
return res
def test_branching_interpret():
- from pypy.rpython import rgenop
+ from pypy.jit.codegen.llgraph.rgenop import rgenop
gv_branchingfn = make_branching(rgenop)
- branchingfn = rgenop.revealconst(lltype.Ptr(FUNC2), gv_branchingfn)
+ branchingfn = gv_branchingfn.revealconst(lltype.Ptr(FUNC2))
llinterp = LLInterpreter(None)
res = llinterp.eval_graph(branchingfn._obj.graph, [30, 17])
assert res == 29
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 Wed Aug 23 18:47:27 2006
@@ -12,6 +12,7 @@
from pypy.rpython.module.support import LLSupport
from pypy.rpython.extregistry import ExtRegistryEntry
from pypy.rpython.llinterp import LLInterpreter
+from pypy.rpython.lltypesystem.rclass import fishllattr
# for debugging, sanity checks in non-RPython code
@@ -42,13 +43,13 @@
def _inputvars(vars):
if not isinstance(vars, list):
n = vars.ll_length()
- vars = [getattr(llvar, 'inst_v', llvar) for llvar in vars.ll_items()]
+ vars = vars.ll_items()
+ vars = [fishllattr(vars[i], 'v', vars[i]) for i in range(n)]
else:
- n = len(vars)
vars = [getattr(llvar, 'v', llvar) for llvar in vars]
res = []
- for i in range(n):
- v = from_opaque_object(vars[i])
+ for v1 in vars:
+ v = from_opaque_object(v1)
assert isinstance(v, (flowmodel.Constant, flowmodel.Variable))
res.append(v)
return res
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 Wed Aug 23 18:47:27 2006
@@ -1,7 +1,8 @@
from pypy.rpython.lltypesystem import lltype
-from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock
+from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenLink
from pypy.jit.codegen.model import GenVar, GenConst
from pypy.jit.codegen.llgraph import llimpl
+from pypy.rpython.lltypesystem.rclass import fishllattr
class LLVar(GenVar):
@@ -18,6 +19,9 @@
revealconst._annspecialcase_ = 'specialize:arg(1)'
+gv_Void = LLConst(llimpl.constTYPE(lltype.Void))
+
+
class LLBlock(CodeGenBlock):
def __init__(self, b):
self.b = b
@@ -25,8 +29,9 @@
def geninputarg(self, gv_TYPE):
return LLVar(llimpl.geninputarg(self.b, gv_TYPE.v))
- def genop(self, opname, vars_gv, gv_RESULT_TYPE):
- return LLVar(llimpl.genop(self.b, opname, vars_gv, gv_RESULT_TYPE.v))
+ 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))
genop._annspecialcase_ = 'specialize:arg(1)'
def close1(self):
@@ -49,6 +54,7 @@
class RGenOp(AbstractRGenOp):
+ gv_Void = gv_Void
def newblock(self):
return LLBlock(llimpl.newblock())
@@ -68,7 +74,7 @@
constTYPE = staticmethod(constTYPE)
def placeholder(dummy):
- return LLConst(llimpl.placerholder(dummy))
+ return LLConst(llimpl.placeholder(dummy))
placeholder._annspecialcase_ = 'specialize:arg(0)'
placeholder = staticmethod(placeholder)
@@ -76,3 +82,31 @@
return LLConst(llimpl.constFieldName(name))
constFieldName._annspecialcase_ = 'specialize:memo'
constFieldName = staticmethod(constFieldName)
+
+ constPrebuiltGlobal = genconst
+
+ # not RPython, just for debugging. Specific to llgraph.
+ def reveal(gv):
+ return llimpl.reveal(gv.v)
+ reveal = staticmethod(reveal)
+
+ # Builds a real flow.model.FunctionGraph. Specific to llgraph.
+ def buildgraph(block):
+ if hasattr(block, 'b'):
+ b = block.b
+ else:
+ b = fishllattr(block, 'b')
+ return llimpl.buildgraph(b)
+ buildgraph = staticmethod(buildgraph)
+
+ testgengraph = staticmethod(llimpl.testgengraph)
+
+ def get_rgenop_for_testing():
+ return rgenop
+ get_rgenop_for_testing = staticmethod(get_rgenop_for_testing)
+
+ def _freeze_(self):
+ return True # no real point in using a full class in llgraph
+
+
+rgenop = RGenOp() # no real point in using a full class in llgraph
Modified: pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py (original)
+++ pypy/dist/pypy/jit/llabstractinterp/llabstractinterp.py Wed Aug 23 18:47:27 2006
@@ -10,7 +10,7 @@
from pypy.jit.llabstractinterp.llcontainer import LLAbstractContainer
from pypy.jit.llabstractinterp.llcontainer import virtualcontainervalue
from pypy.jit.llabstractinterp.llcontainer import hasllcontent
-from pypy.rpython import rgenop
+from pypy.jit.codegen.llgraph.rgenop import rgenop
# ____________________________________________________________
@@ -264,7 +264,7 @@
self.target_set = False
def setreturn(self):
- rgenop.closereturnlink(self.link, self.args_genv[0])
+ self.link.closereturn(self.args_genv[0])
self.target_set = True
def settarget(self, block, blockargs):
@@ -277,7 +277,7 @@
assert v1.value == v2.value
else:
args.append(v1)
- rgenop.closelink(self.link, args, block)
+ self.link.close(args, block)
self.target_set = True
class GraphState(object):
@@ -524,14 +524,14 @@
def buildblock(self, newexitswitch, newlinkstates):
b = self.newblock
if newexitswitch is None:
- link = rgenop.closeblock1(b)
+ link = b.close1()
newlinkstates[0].link = link
return b
assert len(newlinkstates) == 2
v = newexitswitch.getgenvar(self)
- false_link, true_link = rgenop.closeblock2(b, v)
+ false_link, true_link = b.close2(v)
cases = {False: false_link, True: true_link}
for ls in newlinkstates:
@@ -539,14 +539,17 @@
return b
def genop(self, opname, args, RESULT_TYPE=lltype.Void):
- return rgenop.genop(self.newblock, opname, args,
- rgenop.constTYPE(RESULT_TYPE))
+ return self.newblock.genop(opname, args,
+ rgenop.constTYPE(RESULT_TYPE))
def genconst(self, llvalue):
return rgenop.genconst(llvalue)
def genvoidconst(self, placeholder):
return rgenop.placeholder(placeholder)
+
+ def constTYPE(self, T):
+ return T
def binding(self, v):
assert isinstance(v, (Constant, Variable))
Modified: pypy/dist/pypy/jit/llabstractinterp/llcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/llcontainer.py (original)
+++ pypy/dist/pypy/jit/llabstractinterp/llcontainer.py Wed Aug 23 18:47:27 2006
@@ -1,6 +1,6 @@
from pypy.rpython.lltypesystem import lltype
from pypy.jit.llabstractinterp.llvalue import LLAbstractValue, AConstant, const
-from pypy.rpython import rgenop
+from pypy.jit.codegen.llgraph.rgenop import rgenop
class LLAbstractContainer(object):
"""Abstract base class for abstract containers.
@@ -51,7 +51,8 @@
def build_runtime_container(self, builder):
RESULT_TYPE = lltype.Ptr(self.T)
if self.a_parent is not None:
- parentindex = rgenop.constFieldName(self.parentindex)
+ PARENT_TYPE = self.a_parent.getconcretetype().TO
+ parentindex = rgenop.constFieldName(PARENT_TYPE, self.parentindex)
v_parent = self.a_parent.forcegenvarorconst(builder)
v_result = builder.genop('getsubstruct',
[v_parent, parentindex], RESULT_TYPE)
@@ -75,8 +76,9 @@
T = self.fieldtype(name)
if isinstance(T, lltype.ContainerType):
# initialize the substructure/subarray
+ c_name = rgenop.constFieldName(self.T, name)
v_subptr = builder.genop('getsubstruct',
- [v_target, rgenop.constFieldName(name)],
+ [v_target, c_name],
lltype.Ptr(T))
assert isinstance(a_value.content, LLVirtualContainer)
a_value.content.buildcontent(builder, v_subptr)
@@ -165,7 +167,8 @@
return getattr(self.T, name)
def setop(self, builder, v_target, name, v_value):
- builder.genop('setfield', [v_target, rgenop.constFieldName(name), v_value],
+ c_name = rgenop.constFieldName(self.T, name)
+ builder.genop('setfield', [v_target, c_name, v_value],
lltype.Void)
Modified: pypy/dist/pypy/jit/llabstractinterp/llvalue.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/llvalue.py (original)
+++ pypy/dist/pypy/jit/llabstractinterp/llvalue.py Wed Aug 23 18:47:27 2006
@@ -1,6 +1,6 @@
from pypy.objspace.flow.model import Constant
from pypy.rpython.lltypesystem import lltype
-from pypy.rpython import rgenop
+from pypy.jit.codegen.llgraph.rgenop import rgenop
from pypy.tool.uid import Hashable
class AVariable(object):
@@ -202,7 +202,7 @@
assert c.concretetype == self.concretetype
result = LLAbstractValue(c)
else:
- gen_v = rgenop.geninputarg(block, rgenop.constTYPE(self.concretetype))
+ gen_v = block.geninputarg(rgenop.constTYPE(self.concretetype))
result = LLAbstractValue(AVariable(self.concretetype, genvar=gen_v))
result.origin.append(self)
return result
Modified: pypy/dist/pypy/jit/timeshifter/oop.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/oop.py (original)
+++ pypy/dist/pypy/jit/timeshifter/oop.py Wed Aug 23 18:47:27 2006
@@ -1,5 +1,4 @@
from pypy.rpython.lltypesystem import lltype
-from pypy.rpython import rgenop
from pypy.jit.timeshifter.rcontainer import cachedtype
from pypy.jit.timeshifter import rvalue
@@ -12,7 +11,7 @@
class OopSpecDesc:
__metaclass__ = cachedtype
- def __init__(self, fnobj):
+ def __init__(self, RGenOp, fnobj):
ll_func = fnobj._callable
FUNCTYPE = lltype.typeOf(fnobj)
nb_args = len(FUNCTYPE.ARGS)
@@ -37,14 +36,14 @@
ARGTYPE = FUNCTYPE.ARGS[i]
assert ((i+1) in self.argpositions) == (ARGTYPE is not lltype.Void)
- self.args_gv = [rgenop.placeholder(None)] * nb_args
- self.args_gv.insert(0, rgenop.genconst(fnobj._as_ptr()))
- self.gv_result_type = rgenop.constTYPE(FUNCTYPE.RESULT)
+ self.args_gv = [RGenOp.placeholder(None)] * nb_args
+ self.args_gv.insert(0, RGenOp.constPrebuiltGlobal(fnobj._as_ptr()))
+ self.gv_result_type = RGenOp.constTYPE(FUNCTYPE.RESULT)
self.redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT)
if operation_name == 'newlist':
from pypy.jit.timeshifter.vlist import ListTypeDesc, oop_newlist
- self.typedesc = ListTypeDesc(FUNCTYPE.RESULT.TO)
+ self.typedesc = ListTypeDesc(RGenOp, FUNCTYPE.RESULT.TO)
self.ll_handler = oop_newlist
else:
typename, method = operation_name.split('.')
Modified: pypy/dist/pypy/jit/timeshifter/rcontainer.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rcontainer.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rcontainer.py Wed Aug 23 18:47:27 2006
@@ -1,6 +1,5 @@
import operator
from pypy.rpython.lltypesystem import lltype
-from pypy.rpython import rgenop
from pypy.jit.timeshifter import rvalue
class AbstractContainer(object):
@@ -30,28 +29,29 @@
__metaclass__ = cachedtype
firstsubstructdesc = None
- def __init__(self, TYPE):
+ def __init__(self, RGenOp, TYPE):
self.TYPE = TYPE
self.PTRTYPE = lltype.Ptr(TYPE)
- self.gv_type = rgenop.constTYPE(self.TYPE)
- self.gv_ptrtype = rgenop.constTYPE(self.PTRTYPE)
+ self.gv_type = RGenOp.constTYPE(self.TYPE)
+ self.gv_ptrtype = RGenOp.constTYPE(self.PTRTYPE)
fielddescs = []
for name in self.TYPE._names:
FIELDTYPE = getattr(self.TYPE, name)
if isinstance(FIELDTYPE, lltype.ContainerType):
- substructdesc = StructTypeDesc(FIELDTYPE)
+ substructdesc = StructTypeDesc(RGenOp, FIELDTYPE)
assert name == self.TYPE._names[0], (
"unsupported: inlined substructures not as first field")
self.firstsubstructdesc = substructdesc
for subfielddesc in substructdesc.fielddescs:
dottedname = '%s.%s' % (name, subfielddesc.fieldname)
index = len(fielddescs)
- fielddescs.append(StructFieldDesc(self.PTRTYPE, dottedname,
- index))
+ fielddescs.append(StructFieldDesc(RGenOp, self.PTRTYPE,
+ dottedname, index))
else:
index = len(fielddescs)
- fielddescs.append(StructFieldDesc(self.PTRTYPE, name, index))
+ fielddescs.append(StructFieldDesc(RGenOp, self.PTRTYPE,
+ name, index))
self.fielddescs = fielddescs
def getfielddesc(self, name):
@@ -79,12 +79,12 @@
class FieldDesc(object):
__metaclass__ = cachedtype
- def __init__(self, PTRTYPE, RESTYPE):
+ def __init__(self, RGenOp, PTRTYPE, RESTYPE):
self.PTRTYPE = PTRTYPE
if isinstance(RESTYPE, lltype.ContainerType):
RESTYPE = lltype.Ptr(RESTYPE)
self.RESTYPE = RESTYPE
- self.gv_resulttype = rgenop.constTYPE(RESTYPE)
+ self.gv_resulttype = RGenOp.constTYPE(RESTYPE)
self.redboxcls = rvalue.ll_redboxcls(RESTYPE)
self.immutable = PTRTYPE.TO._hints.get('immutable', False)
@@ -93,8 +93,8 @@
class NamedFieldDesc(FieldDesc):
- def __init__(self, PTRTYPE, name):
- FieldDesc.__init__(self, PTRTYPE, getattr(PTRTYPE.TO, name))
+ def __init__(self, RGenOp, PTRTYPE, name):
+ FieldDesc.__init__(self, RGenOp, PTRTYPE, getattr(PTRTYPE.TO, name))
self.structdepth = 0
T = self.PTRTYPE.TO
while (T._names and
@@ -102,33 +102,35 @@
self.structdepth += 1
T = getattr(T, T._names[0])
self.fieldname = name
- self.gv_fieldname = rgenop.constFieldName(name)
+ self.gv_fieldname = RGenOp.constFieldName(T, name)
class ArrayFieldDesc(FieldDesc):
- def __init__(self, PTRTYPE):
+ def __init__(self, RGenOp, PTRTYPE):
assert isinstance(PTRTYPE.TO, lltype.Array)
- FieldDesc.__init__(self, PTRTYPE, PTRTYPE.TO.OF)
+ FieldDesc.__init__(self, RGenOp, PTRTYPE, PTRTYPE.TO.OF)
class StructFieldDesc(object):
__metaclass__ = cachedtype
- def __init__(self, PTRTYPE, fieldname, index):
+ def __init__(self, RGenOp, PTRTYPE, fieldname, index):
assert isinstance(PTRTYPE.TO, lltype.Struct)
RES1 = PTRTYPE.TO
accessptrtype_gv = self.accessptrtype_gv = []
+ accessors = []
for component in fieldname.split('.'):
LASTSTRUCT = RES1
- accessptrtype_gv.append(rgenop.constTYPE(lltype.Ptr(LASTSTRUCT)))
+ accessptrtype_gv.append(RGenOp.constTYPE(lltype.Ptr(LASTSTRUCT)))
+ accessors.append((RES1, component))
RES1 = getattr(RES1, component)
assert not isinstance(RES1, lltype.ContainerType)
self.PTRTYPE = PTRTYPE
self.RESTYPE = RES1
- self.gv_resulttype = rgenop.constTYPE(RES1)
+ self.gv_resulttype = RGenOp.constTYPE(RES1)
self.fieldname = fieldname
- self.fieldname_gv = [rgenop.constFieldName(component)
- for component in fieldname.split('.')]
+ self.fieldname_gv = [RGenOp.constFieldName(T, component)
+ for T, component in accessors]
self.fieldindex = index
- self.gv_default = rgenop.genconst(RES1._defl())
+ self.gv_default = RGenOp.constPrebuiltGlobal(RES1._defl())
self.redboxcls = rvalue.ll_redboxcls(RES1)
self.immutable = LASTSTRUCT._hints.get('immutable', False)
@@ -149,7 +151,7 @@
op_args = [gv_sub,
self.fieldname_gv[-1],
box.getgenvar(builder)]
- genop('setfield', op_args, rgenop.gv_Void)
+ genop('setfield', op_args, builder.rgenop.gv_Void)
# ____________________________________________________________
Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py Wed Aug 23 18:47:27 2006
@@ -1,6 +1,5 @@
import operator, weakref
from pypy.rpython.lltypesystem import lltype, lloperation, llmemory
-from pypy.rpython import rgenop
from pypy.jit.timeshifter import rvalue
FOLDABLE_OPS = dict.fromkeys(lloperation.enum_foldable_ops())
@@ -19,13 +18,14 @@
def _freeze_(self):
return True
- def __init__(self, opname, ARGS, RESULT):
+ def __init__(self, RGenOp, opname, ARGS, RESULT):
+ self.RGenOp = RGenOp
self.opname = opname
self.llop = lloperation.LL_OPERATIONS[opname]
self.nb_args = len(ARGS)
self.ARGS = ARGS
self.RESULT = RESULT
- self.gv_RESULT = rgenop.constTYPE(RESULT)
+ self.gv_RESULT = RGenOp.constTYPE(RESULT)
self.redboxcls = rvalue.ll_redboxcls(RESULT)
self.canfold = opname in FOLDABLE_OPS
@@ -43,7 +43,7 @@
def make_opdesc(hop):
hrtyper = hop.rtyper
- op_key = (hop.spaceop.opname,
+ op_key = (hrtyper.RGenOp, hop.spaceop.opname,
tuple([hrtyper.originalconcretetype(s_arg) for s_arg in hop.args_s]),
hrtyper.originalconcretetype(hop.s_result))
try:
@@ -60,7 +60,7 @@
if opdesc.canfold and argbox.is_constant():
arg = rvalue.ll_getvalue(argbox, ARG0)
res = opdesc.llop(RESULT, arg)
- return rvalue.ll_fromvalue(res)
+ return rvalue.ll_fromvalue(jitstate, res)
op_args = [argbox.getgenvar(jitstate.curbuilder)]
genvar = jitstate.curbuilder.genop(opdesc.opname, op_args,
opdesc.gv_RESULT)
@@ -76,7 +76,7 @@
arg0 = rvalue.ll_getvalue(argbox0, ARG0)
arg1 = rvalue.ll_getvalue(argbox1, ARG1)
res = opdesc.llop(RESULT, arg0, arg1)
- return rvalue.ll_fromvalue(res)
+ return rvalue.ll_fromvalue(jitstate, res)
op_args = [argbox0.getgenvar(jitstate.curbuilder),
argbox1.getgenvar(jitstate.curbuilder)]
genvar = jitstate.curbuilder.genop(opdesc.opname, op_args,
@@ -87,7 +87,7 @@
if fielddesc.immutable and argbox.is_constant():
res = getattr(rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE),
fielddesc.fieldname)
- return rvalue.ll_fromvalue(res)
+ return rvalue.ll_fromvalue(jitstate, res)
assert isinstance(argbox, rvalue.PtrRedBox)
if argbox.content is None:
op_args = [argbox.getgenvar(jitstate.curbuilder),
@@ -104,8 +104,8 @@
op_args = [destbox.getgenvar(jitstate.curbuilder),
fielddesc.fieldname_gv[-1],
valuebox.getgenvar(jitstate.curbuilder)]
- jitstate.curbuilder.genop('setfield', op_args,
- rgenop.gv_Void)
+ builder = jitstate.curbuilder
+ builder.genop('setfield', op_args, builder.rgenop.gv_Void)
else:
destbox.content.op_setfield(jitstate, fielddesc, valuebox)
@@ -113,7 +113,7 @@
if argbox.is_constant():
res = getattr(rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE),
fielddesc.fieldname)
- return rvalue.ll_fromvalue(res)
+ return rvalue.ll_fromvalue(jitstate, res)
assert isinstance(argbox, rvalue.PtrRedBox)
if argbox.content is None:
op_args = [argbox.getgenvar(jitstate.curbuilder),
@@ -129,7 +129,7 @@
if fielddesc.immutable and argbox.is_constant() and indexbox.is_constant():
array = rvalue.ll_getvalue(argbox, fielddesc.PTRTYPE)
res = array[rvalue.ll_getvalue(indexbox, lltype.Signed)]
- return rvalue.ll_fromvalue(res)
+ return rvalue.ll_fromvalue(jitstate, res)
op_args = [argbox.getgenvar(jitstate.curbuilder),
indexbox.getgenvar(jitstate.curbuilder)]
genvar = jitstate.curbuilder.genop('getarrayitem', op_args,
@@ -143,6 +143,7 @@
return builder.build_jitstate(backstate)
def retrieve_jitstate_for_merge(states_dic, jitstate, key, redboxes):
+ rgenop = jitstate.rgenop
mylocalredboxes = redboxes
redboxes = list(redboxes)
jitstate.extend_with_parent_locals(redboxes)
@@ -158,7 +159,7 @@
linkargs = []
for box in outgoingvarboxes:
linkargs.append(box.getgenvar(None))
- box.genvar = rgenop.geninputarg(newblock, box.gv_type)
+ box.genvar = newblock.geninputarg(box.gv_type)
jitstate.curbuilder.enter_block(linkargs, newblock)
states_dic[key] = frozens, newblock
return jitstate
@@ -191,7 +192,7 @@
for box in outgoingvarboxes:
if box.is_constant(): # constant boxes considered immutable:
box = box.copy(replace_memo) # copy to avoid patching the original
- box.genvar = rgenop.geninputarg(newblock, box.gv_type)
+ box.genvar = newblock.geninputarg(box.gv_type)
if replace_memo.boxes:
for i in range(len(mylocalredboxes)):
newbox = redboxes[i].replace(replace_memo)
@@ -206,6 +207,7 @@
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()
@@ -224,6 +226,7 @@
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()
@@ -269,15 +272,16 @@
retrieve_jitstate_for_merge(cache, jitstate, (), [retbox])
frozens, block = cache[()]
_, returnbox = jitstate.return_queue[-1]
- builder = ResidualGraphBuilder(block)
+ rgenop = jitstate.rgenop
+ builder = ResidualGraphBuilder(rgenop, block)
builder.valuebox = returnbox
return builder
def ll_gvar_from_redbox(jitstate, redbox):
return redbox.getgenvar(jitstate.curbuilder)
-def ll_gvar_from_constant(ll_value):
- return rgenop.genconst(ll_value)
+def ll_gvar_from_constant(jitstate, ll_value):
+ return jitstate.rgenop.genconst(ll_value)
def save_locals(jitstate, redboxes):
jitstate.localredboxes = redboxes
@@ -292,43 +296,57 @@
# ____________________________________________________________
-class ResidualGraphBuilder(rgenop.LowLevelOpBuilder):
- def __init__(self, block=rgenop.nullblock, link=rgenop.nulllink):
- rgenop.LowLevelOpBuilder.__init__(self, block)
+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:ll'
+
+ def genvoidconst(self, dummy):
+ return self.rgenop.placeholder(dummy)
+ genvoidconst._annspecialcase_ = 'specialize:arg(1)'
+
+ def genop(self, opname, args_gv, gv_resulttype=None):
+ return self.block.genop(opname, args_gv, gv_resulttype)
+ genop._annspecialcase_ = 'specialize:arg(1)'
+
+ 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):
- rgenop.closelink(self.outgoinglink, linkargs, newblock)
+ self.outgoinglink.close(linkargs, newblock)
self.block = newblock
- self.outgoinglink = rgenop.nulllink
+ self.outgoinglink = None
def leave_block(self):
- self.outgoinglink = rgenop.closeblock1(self.block)
+ self.outgoinglink = self.block.close1()
def leave_block_split(self, exitgvar):
- false_link, true_link = rgenop.closeblock2(self.block, exitgvar)
- later_builder = ResidualGraphBuilder(link=false_link)
+ 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):
- rgenop.closelink(self.outgoinglink, linkargs, targetblock)
- self.outgoinglink = rgenop.nulllink
+ self.outgoinglink.close(linkargs, targetblock)
+ self.outgoinglink = None
def finish_and_return(self):
gv_retval = self.valuebox.getgenvar(self)
- returnlink = rgenop.closeblock1(self.block)
- rgenop.closereturnlink(returnlink, gv_retval)
-
- def clone(self):
- XXX
+ returnlink = self.block.close1()
+ returnlink.closereturn(gv_retval)
-def ll_make_builder():
- return ResidualGraphBuilder(rgenop.newblock())
+def make_builder(rgenop):
+ return ResidualGraphBuilder(rgenop, rgenop.newblock())
def ll_int_box(gv_type, gv):
return rvalue.IntRedBox(gv_type, gv)
@@ -340,7 +358,7 @@
return rvalue.PtrRedBox(gv_type, gv)
def ll_geninputarg(builder, gv_TYPE):
- return rgenop.geninputarg(builder.block, gv_TYPE)
+ return builder.block.geninputarg(gv_TYPE)
def ll_end_setup_builder(builder):
builder.leave_block()
@@ -357,6 +375,7 @@
self.split_queue = []
self.return_queue = []
self.curbuilder = builder
+ self.rgenop = builder.rgenop
self.backstate = backstate
def extend_with_parent_locals(self, redboxes):
Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtyper.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rtyper.py Wed Aug 23 18:47:27 2006
@@ -8,7 +8,6 @@
from pypy.rpython.lltypesystem.rstr import string_repr
from pypy.rpython.typesystem import LowLevelTypeSystem
from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.rpython import rgenop
from pypy.jit.hintannotator import model as hintmodel
from pypy.jit.hintannotator import container as hintcontainer
from pypy.jit.timeshifter import rtimeshift, rvalue, rcontainer
@@ -40,6 +39,7 @@
self.green_reprs = PRECOMPUTED_GREEN_REPRS.copy()
self.red_reprs = {}
self.timeshifter = timeshifter
+ self.RGenOp = timeshifter.RGenOp
originalconcretetype = staticmethod(originalconcretetype)
@@ -127,11 +127,11 @@
ts = self.timeshifter
v_argbox, c_fieldname = hop.inputargs(self.getredrepr(PTRTYPE),
green_void_repr)
- fielddesc = rcontainer.StructTypeDesc(PTRTYPE.TO).getfielddesc(c_fieldname.value)
+ structdesc = rcontainer.StructTypeDesc(self.RGenOp, PTRTYPE.TO)
+ fielddesc = structdesc.getfielddesc(c_fieldname.value)
c_fielddesc = inputconst(lltype.Void, fielddesc)
s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
v_jitstate = hop.llops.getjitstate()
- s_CONSTORVAR = annmodel.SomePtr(rgenop.CONSTORVAR)
return hop.llops.genmixlevelhelpercall(rtimeshift.ll_generate_getfield,
[ts.s_JITState, s_fielddesc, ts.s_RedBox],
[v_jitstate, c_fielddesc, v_argbox ],
@@ -147,11 +147,10 @@
ts = self.timeshifter
v_argbox, v_index = hop.inputargs(self.getredrepr(PTRTYPE),
self.getredrepr(lltype.Signed))
- fielddesc = rcontainer.ArrayFieldDesc(PTRTYPE)
+ fielddesc = rcontainer.ArrayFieldDesc(self.RGenOp, PTRTYPE)
c_fielddesc = inputconst(lltype.Void, fielddesc)
s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
v_jitstate = hop.llops.getjitstate()
- s_CONSTORVAR = annmodel.SomePtr(rgenop.CONSTORVAR)
return hop.llops.genmixlevelhelpercall(rtimeshift.ll_generate_getarrayitem,
[ts.s_JITState, s_fielddesc, ts.s_RedBox, ts.s_RedBox],
[v_jitstate, c_fielddesc, v_argbox, v_index ],
@@ -168,11 +167,11 @@
green_void_repr,
self.getredrepr(VALUETYPE)
)
- fielddesc = rcontainer.StructTypeDesc(PTRTYPE.TO).getfielddesc(c_fieldname.value)
+ structdesc = rcontainer.StructTypeDesc(self.RGenOp, PTRTYPE.TO)
+ fielddesc = structdesc.getfielddesc(c_fieldname.value)
c_fielddesc = inputconst(lltype.Void, fielddesc)
s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
v_jitstate = hop.llops.getjitstate()
- s_CONSTORVAR = annmodel.SomePtr(rgenop.CONSTORVAR)
return hop.llops.genmixlevelhelpercall(rtimeshift.ll_generate_setfield,
[ts.s_JITState, s_fielddesc, ts.s_RedBox, ts.s_RedBox],
[v_jitstate, c_fielddesc, v_destbox, v_valuebox],
@@ -186,11 +185,11 @@
PTRTYPE = originalconcretetype(hop.args_s[0])
v_argbox, c_fieldname = hop.inputargs(self.getredrepr(PTRTYPE),
green_void_repr)
- fielddesc = rcontainer.NamedFieldDesc(PTRTYPE, c_fieldname.value) # XXX
+ fielddesc = rcontainer.NamedFieldDesc(self.RGenOp, PTRTYPE,
+ c_fieldname.value) # XXX
c_fielddesc = inputconst(lltype.Void, fielddesc)
s_fielddesc = ts.rtyper.annotator.bookkeeper.immutablevalue(fielddesc)
v_jitstate = hop.llops.getjitstate()
- s_CONSTORVAR = annmodel.SomePtr(rgenop.CONSTORVAR)
return hop.llops.genmixlevelhelpercall(rtimeshift.ll_generate_getsubstruct,
[ts.s_JITState, s_fielddesc, ts.s_RedBox],
[v_jitstate, c_fielddesc, v_argbox ],
@@ -257,7 +256,7 @@
def handle_highlevel_operation(self, fnobj, hop):
from pypy.jit.timeshifter.oop import OopSpecDesc, Index
- oopspecdesc = OopSpecDesc(fnobj)
+ oopspecdesc = OopSpecDesc(self.RGenOp, fnobj)
args_v = []
for obj in oopspecdesc.argtuple:
@@ -424,10 +423,11 @@
return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_redbox,
[ts.s_JITState, llops.timeshifter.s_RedBox],
[v_jitstate, v],
- annmodel.SomePtr(rgenop.CONSTORVAR))
+ ts.s_ConstOrVar)
def convert_const(self, ll_value):
- redbox = rvalue.ll_fromvalue(ll_value)
+ RGenOp = self.timeshifter.RGenOp
+ redbox = rvalue.redbox_from_prebuilt_value(RGenOp, ll_value)
timeshifter = self.timeshifter
return timeshifter.annhelper.delayedconst(timeshifter.r_RedBox, redbox)
@@ -439,10 +439,10 @@
typedesc = None
def create(self, hop):
+ ts = self.timeshifter
if self.typedesc is None:
T = self.original_concretetype.TO
- self.typedesc = rcontainer.StructTypeDesc(T)
- ts = self.timeshifter
+ self.typedesc = rcontainer.StructTypeDesc(ts.RGenOp, T)
return hop.llops.genmixlevelhelpercall(self.typedesc.ll_factory,
[], [], ts.s_RedBox)
@@ -597,9 +597,12 @@
return annmodel.SomeInteger()
def get_genop_var(self, v, llops):
+ ts = self.timeshifter
+ v_jitstate = hop.llops.getjitstate()
return llops.genmixlevelhelpercall(rtimeshift.ll_gvar_from_constant,
- [self.annotation()], [v],
- annmodel.SomePtr(rgenop.CONSTORVAR))
+ [ts.s_JITState, self.annotation()],
+ [v_jitstate, v],
+ ts.s_ConstOrVar)
def convert_const(self, ll_value):
return ll_value
@@ -624,9 +627,12 @@
def convert_from_to((r_from, r_to), v, llops):
assert r_from.lowleveltype == r_to.original_concretetype
+ ts = llops.timeshifter
+ v_jitstate = llops.getjitstate()
return llops.genmixlevelhelpercall(rvalue.ll_fromvalue,
- [r_from.annotation()], [v],
- llops.timeshifter.s_RedBox)
+ [ts.s_JITState, r_from.annotation()],
+ [v_jitstate, v],
+ llops.timeshifter.s_RedBox)
# ____________________________________________________________
Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rvalue.py (original)
+++ pypy/dist/pypy/jit/timeshifter/rvalue.py Wed Aug 23 18:47:27 2006
@@ -1,4 +1,3 @@
-from pypy.rpython import rgenop
from pypy.rpython.lltypesystem import lltype, llmemory
class Memo(object):
@@ -14,8 +13,8 @@
def freeze_memo():
return Memo()
-def unfreeze_memo():
- return {} # Memo()
+##def unfreeze_memo():
+## return {} # Memo()
def exactmatch_memo():
return Memo()
@@ -26,19 +25,20 @@
class RedBox(object):
- def __init__(self, gv_type, genvar=rgenop.nullvar):
- assert rgenop.isconst(gv_type) # temporary?
+ def __init__(self, gv_type, genvar=None):
+ assert gv_type.is_const
self.gv_type = gv_type
- self.genvar = genvar # nullvar or a genvar
+ self.genvar = genvar # None or a genvar
def __repr__(self):
if not self.genvar:
return '<dummy>'
else:
+ from pypy.jit.codegen.llgraph.rgenop import rgenop
return '<%r>' % (rgenop.reveal(self.genvar),)
def is_constant(self):
- return bool(self.genvar) and rgenop.isconst(self.genvar)
+ return bool(self.genvar) and self.genvar.is_const
def getgenvar(self, builder):
return self.genvar
@@ -48,7 +48,7 @@
if not self.is_constant() and self not in memo:
incoming.append(self.genvar)
memo[self] = None
- self.genvar = rgenop.geninputarg(newblock, self.gv_type)
+ self.genvar = newblock.geninputarg(self.gv_type)
def replace(self, memo):
memo = memo.boxes
@@ -83,17 +83,25 @@
# XXX what about long longs?
return redboxbuilder_int
-def ll_fromvalue(value):
+def ll_fromvalue(jitstate, value):
"Make a constant RedBox from a low-level value."
+ rgenop = jitstate.rgenop
T = lltype.typeOf(value)
gv_type = rgenop.constTYPE(T)
gv = rgenop.genconst(value)
cls = ll_redboxcls(T)
return cls(gv_type, gv)
+def redbox_from_prebuilt_value(RGenOp, value):
+ T = lltype.typeOf(value)
+ gv_type = RGenOp.constTYPE(T)
+ gv = RGenOp.constPrebuiltGlobal(value)
+ cls = ll_redboxcls(T)
+ return cls(gv_type, gv)
+
def ll_getvalue(box, T):
"Return the content of a known-to-be-constant RedBox."
- return rgenop.revealconst(T, box.genvar)
+ return box.genvar.revealconst(T)
class IntRedBox(RedBox):
@@ -216,17 +224,17 @@
def __init__(self, gv_const):
self.gv_const = gv_const
- def unfreeze(self, memo, block, gv_type):
- try:
- return memo[self]
- except KeyError:
- box = memo[self] = IntRedBox(gv_type, self.gv_const)
- return box
+## def unfreeze(self, memo, block, gv_type):
+## try:
+## return memo[self]
+## except KeyError:
+## box = memo[self] = IntRedBox(gv_type, self.gv_const)
+## return box
def exactmatch(self, box, outgoingvarboxes, memo):
if (box.is_constant() and
- rgenop.revealconst(lltype.Signed, self.gv_const) ==
- rgenop.revealconst(lltype.Signed, box.genvar)):
+ self.gv_const.revealconst(lltype.Signed) ==
+ box.genvar.revealconst(lltype.Signed)):
return True
else:
outgoingvarboxes.append(box)
@@ -235,13 +243,13 @@
class FrozenIntVar(FrozenValue):
- def unfreeze(self, memo, block, gv_type):
- try:
- return memo[self]
- except KeyError:
- gv_value = rgenop.geninputarg(block, gv_type)
- box = memo[self] = IntRedBox(gv_type, gv_value)
- return box
+## def unfreeze(self, memo, block, gv_type):
+## try:
+## return memo[self]
+## except KeyError:
+## gv_value = rgenop.geninputarg(block, gv_type)
+## box = memo[self] = IntRedBox(gv_type, gv_value)
+## return box
def exactmatch(self, box, outgoingvarboxes, memo):
memo = memo.boxes
@@ -261,17 +269,17 @@
def __init__(self, gv_const):
self.gv_const = gv_const
- def unfreeze(self, memo, block, gv_type):
- try:
- return memo[self]
- except KeyError:
- box = memo[self] = DoubleRedBox(gv_type, self.gv_const)
- return box
+## def unfreeze(self, memo, block, gv_type):
+## try:
+## return memo[self]
+## except KeyError:
+## box = memo[self] = DoubleRedBox(gv_type, self.gv_const)
+## return box
def exactmatch(self, box, outgoingvarboxes, memo):
if (box.is_constant() and
- rgenop.revealconst(lltype.Float, self.gv_const) ==
- rgenop.revealconst(lltype.Float, box.genvar)):
+ self.gv_const.revealconst(lltype.Float) ==
+ box.genvar.revealconst(lltype.Float)):
return True
else:
outgoingvarboxes.append(box)
@@ -280,13 +288,13 @@
class FrozenDoubleVar(FrozenValue):
- def unfreeze(self, memo, block, gv_type):
- try:
- return memo[self]
- except KeyError:
- gv_value = rgenop.geninputarg(block, gv_type)
- box = memo[self] = DoubleRedBox(gv_type, gv_value)
- return box
+## def unfreeze(self, memo, block, gv_type):
+## try:
+## return memo[self]
+## except KeyError:
+## gv_value = rgenop.geninputarg(block, gv_type)
+## box = memo[self] = DoubleRedBox(gv_type, gv_value)
+## return box
def exactmatch(self, box, outgoingvarboxes, memo):
memo = memo.boxes
@@ -306,17 +314,17 @@
def __init__(self, gv_const):
self.gv_const = gv_const
- def unfreeze(self, memo, block, gv_type):
- try:
- return memo[self]
- except KeyError:
- box = memo[self] = PtrRedBox(gv_type, self.gv_const)
- return box
+## def unfreeze(self, memo, block, gv_type):
+## try:
+## return memo[self]
+## except KeyError:
+## box = memo[self] = PtrRedBox(gv_type, self.gv_const)
+## return box
def exactmatch(self, box, outgoingvarboxes, memo):
if (box.is_constant() and
- rgenop.revealconst(llmemory.Address, self.gv_const) ==
- rgenop.revealconst(llmemory.Address, box.genvar)):
+ self.gv_const.revealconst(llmemory.Address) ==
+ box.genvar.revealconst(llmemory.Address)):
return True
else:
outgoingvarboxes.append(box)
@@ -325,13 +333,13 @@
class FrozenPtrVar(FrozenValue):
- def unfreeze(self, memo, block, gv_type):
- try:
- return memo[self]
- except KeyError:
- gv_value = rgenop.geninputarg(block, gv_type)
- box = memo[self] = PtrRedBox(gv_type, gv_value)
- return box
+## def unfreeze(self, memo, block, gv_type):
+## try:
+## return memo[self]
+## except KeyError:
+## gv_value = rgenop.geninputarg(block, gv_type)
+## box = memo[self] = PtrRedBox(gv_type, gv_value)
+## return box
def exactmatch(self, box, outgoingvarboxes, memo):
memo = memo.boxes
@@ -348,13 +356,13 @@
class FrozenPtrVirtual(FrozenValue):
- def unfreeze(self, memo, block, gv_type):
- try:
- return memo[self]
- except KeyError:
- box = memo[self] = PtrRedBox(gv_type)
- box.content = self.fz_content.unfreeze(memo, block)
- return box
+## def unfreeze(self, memo, block, gv_type):
+## try:
+## return memo[self]
+## except KeyError:
+## box = memo[self] = PtrRedBox(gv_type)
+## box.content = self.fz_content.unfreeze(memo, block)
+## return box
def exactmatch(self, box, outgoingvarboxes, memo):
assert isinstance(box, PtrRedBox)
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 Wed Aug 23 18:47:27 2006
@@ -9,7 +9,6 @@
from pypy.jit.llabstractinterp.test.test_llabstractinterp import summary
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rpython.objectmodel import hint, keepalive_until_here
-from pypy.rpython import rgenop
from pypy.rpython.lltypesystem import rstr
from pypy.annotation import model as annmodel
from pypy.rpython.llinterp import LLInterpreter
@@ -45,547 +44,533 @@
hannotator.translator.view()
return hs, hannotator, rtyper
-_cache = {}
-_cache_order = []
-def timeshift_cached(ll_function, values, inline, policy):
- key = ll_function, inline, policy
- try:
- result, argtypes = _cache[key]
- except KeyError:
- if len(_cache_order) >= 3:
- del _cache[_cache_order.pop(0)]
- hs, ha, rtyper = hannotate(ll_function, values,
- inline=inline, policy=policy)
- htshift = HintTimeshift(ha, rtyper)
- htshift.timeshift()
- t = rtyper.annotator.translator
- for graph in ha.translator.graphs:
- checkgraph(graph)
- t.graphs.append(graph)
- if conftest.option.view:
- from pypy.translator.tool.graphpage import FlowGraphPage
- FlowGraphPage(t, ha.translator.graphs).display()
- result = hs, ha, rtyper, htshift
- _cache[key] = result, getargtypes(rtyper.annotator, values)
- _cache_order.append(key)
- else:
- hs, ha, rtyper, htshift = result
- assert argtypes == getargtypes(rtyper.annotator, values)
- return result
-
-def timeshift(ll_function, values, opt_consts=[], inline=None, policy=None):
- hs, ha, rtyper, htshift = timeshift_cached(ll_function, values,
- inline, policy)
- # run the time-shifted graph-producing graphs
- graph1 = ha.translator.graphs[0]
- llinterp = LLInterpreter(rtyper)
- builder = llinterp.eval_graph(htshift.ll_make_builder_graph, [])
- graph1args = [builder, lltype.nullptr(htshift.r_JITState.lowleveltype.TO)]
- residual_graph_args = []
- assert len(graph1.getargs()) == 2 + len(values)
- for i, (v, llvalue) in enumerate(zip(graph1.getargs()[2:], values)):
- r = htshift.hrtyper.bindingrepr(v)
- residual_v = r.residual_values(llvalue)
- if len(residual_v) == 0:
- # green
- graph1args.append(llvalue)
+class TimeshiftingTests(object):
+ from pypy.jit.codegen.llgraph.rgenop import RGenOp
+
+ def setup_class(cls):
+ cls._cache = {}
+ cls._cache_order = []
+
+ def teardown_class(cls):
+ del cls._cache
+ del cls._cache_order
+
+ def timeshift_cached(self, ll_function, values, inline, policy):
+ key = ll_function, inline, policy
+ try:
+ result, argtypes = self._cache[key]
+ except KeyError:
+ if len(self._cache_order) >= 3:
+ del self._cache[self._cache_order.pop(0)]
+ hs, ha, rtyper = hannotate(ll_function, values,
+ inline=inline, policy=policy)
+ htshift = HintTimeshift(ha, rtyper, self.RGenOp)
+ htshift.timeshift()
+ t = rtyper.annotator.translator
+ for graph in ha.translator.graphs:
+ checkgraph(graph)
+ t.graphs.append(graph)
+ if conftest.option.view:
+ from pypy.translator.tool.graphpage import FlowGraphPage
+ FlowGraphPage(t, ha.translator.graphs).display()
+ result = hs, ha, rtyper, htshift
+ self._cache[key] = result, getargtypes(rtyper.annotator, values)
+ self._cache_order.append(key)
else:
- # red
- assert residual_v == [llvalue], "XXX for now"
- TYPE = htshift.originalconcretetype(v)
- gv_type = rgenop.constTYPE(TYPE)
- gvar = llinterp.eval_graph(htshift.ll_geninputarg_graph, [builder,
- gv_type])
- if i in opt_consts: # XXX what should happen here interface wise is unclear
- gvar = rgenop.genconst(llvalue)
- if isinstance(lltype.typeOf(llvalue), lltype.Ptr):
- ll_box_graph = htshift.ll_addr_box_graph
- elif isinstance(llvalue, float):
- ll_box_graph = htshift.ll_double_box_graph
+ hs, ha, rtyper, htshift = result
+ assert argtypes == getargtypes(rtyper.annotator, values)
+ return result
+
+ def timeshift(self, ll_function, values, opt_consts=[], inline=None,
+ policy=None):
+ hs, ha, rtyper, htshift = self.timeshift_cached(ll_function, values,
+ inline, policy)
+ # run the time-shifted graph-producing graphs
+ graph1 = ha.translator.graphs[0]
+ llinterp = LLInterpreter(rtyper)
+ builder = llinterp.eval_graph(htshift.ll_make_builder_graph, [])
+ graph1args = [builder, lltype.nullptr(htshift.r_JITState.lowleveltype.TO)]
+ residual_graph_args = []
+ assert len(graph1.getargs()) == 2 + len(values)
+ for i, (v, llvalue) in enumerate(zip(graph1.getargs()[2:], values)):
+ r = htshift.hrtyper.bindingrepr(v)
+ residual_v = r.residual_values(llvalue)
+ if len(residual_v) == 0:
+ # green
+ graph1args.append(llvalue)
else:
- ll_box_graph = htshift.ll_int_box_graph
- box = llinterp.eval_graph(ll_box_graph, [gv_type, gvar])
- graph1args.append(box)
- residual_graph_args.append(llvalue)
- startblock = llinterp.eval_graph(htshift.ll_end_setup_builder_graph, [builder])
-
- builder = llinterp.eval_graph(graph1, graph1args)
- r = htshift.hrtyper.getrepr(hs)
- llinterp.eval_graph(htshift.ll_close_builder_graph, [builder])
-
- # now try to run the blocks produced by the builder
- residual_graph = rgenop.buildgraph(startblock)
- insns = summary(residual_graph)
- res = rgenop.testgengraph(residual_graph, residual_graph_args,
- viewbefore = conftest.option.view)
- return insns, res
-
-##def test_ll_get_return_queue():
-## t = TranslationContext()
-## a = t.buildannotator()
-## rtyper = t.buildrtyper()
-## rtyper.specialize() # XXX
-
-## htshift = HintTimeshift(None, rtyper)
-
-## questate = htshift.QUESTATE_PTR.TO.ll_newstate()
-
-## def llf(questate):
-## return questate.ll_get_return_queue()
-
-## from pypy.rpython import annlowlevel
-
-## graph = annlowlevel.annotate_mixlevel_helper(rtyper, llf, [
-## annmodel.SomePtr(htshift.QUESTATE_PTR)])
-
-## s = a.binding(graph.getreturnvar())
-
-## assert s == htshift.s_return_queue
-
-## rtyper.specialize_more_blocks()
-
-## llinterp = LLInterpreter(rtyper)
-## rq = llinterp.eval_graph(graph, [questate])
-## assert lltype.typeOf(rq) == rtyper.getrepr(s).lowleveltype
-
-
-def test_simple_fixed():
- py.test.skip("green return not working")
- def ll_function(x, y):
- return hint(x + y, concrete=True)
- insns, res = timeshift(ll_function, [5, 7])
- assert res == 12
- assert insns == {}
-
-def test_very_simple():
- def ll_function(x, y):
- return x + y
- insns, res = timeshift(ll_function, [5, 7])
- assert res == 12
- assert insns == {'int_add': 1}
-
-def test_convert_const_to_redbox():
- def ll_function(x, y):
- x = hint(x, concrete=True)
- tot = 0
- while x: # conversion from green '0' to red 'tot'
- tot += y
- x -= 1
- return tot
- insns, res = timeshift(ll_function, [7, 2])
- assert res == 14
- assert insns == {'int_add': 7}
-
-def test_simple_opt_const_propagation2():
- def ll_function(x, y):
- return x + y
- insns, res = timeshift(ll_function, [5, 7], [0, 1])
- assert res == 12
- assert insns == {}
-
-def test_simple_opt_const_propagation1():
- def ll_function(x):
- return -x
- insns, res = timeshift(ll_function, [5], [0])
- assert res == -5
- assert insns == {}
-
-def test_loop_folding():
- def ll_function(x, y):
- tot = 0
- x = hint(x, concrete=True)
- while x:
- tot += y
- x -= 1
- return tot
- insns, res = timeshift(ll_function, [7, 2], [0, 1])
- assert res == 14
- assert insns == {}
-
-def test_loop_merging():
- def ll_function(x, y):
- tot = 0
- while x:
- tot += y
+ # red
+ assert residual_v == [llvalue], "XXX for now"
+ TYPE = htshift.originalconcretetype(v)
+ gv_type = self.RGenOp.constTYPE(TYPE)
+ ll_type = htshift.r_ConstOrVar.convert_const(gv_type)
+ ll_gvar = llinterp.eval_graph(htshift.ll_geninputarg_graph,
+ [builder, ll_type])
+ if i in opt_consts: # XXX what should happen here interface wise is unclear
+ gvar = self.RGenOp.constPrebuiltGlobal(llvalue)
+ ll_gvar = htshift.r_ConstOrVar.convert_const(gvar)
+ if isinstance(lltype.typeOf(llvalue), lltype.Ptr):
+ ll_box_graph = htshift.ll_addr_box_graph
+ elif isinstance(llvalue, float):
+ ll_box_graph = htshift.ll_double_box_graph
+ else:
+ ll_box_graph = htshift.ll_int_box_graph
+ box = llinterp.eval_graph(ll_box_graph, [ll_type, ll_gvar])
+ graph1args.append(box)
+ residual_graph_args.append(llvalue)
+ startblock = llinterp.eval_graph(htshift.ll_end_setup_builder_graph, [builder])
+
+ builder = llinterp.eval_graph(graph1, graph1args)
+ r = htshift.hrtyper.getrepr(hs)
+ llinterp.eval_graph(htshift.ll_close_builder_graph, [builder])
+
+ # now try to run the blocks produced by the builder
+ residual_graph = self.RGenOp.buildgraph(startblock)
+ insns = summary(residual_graph)
+ res = self.RGenOp.testgengraph(residual_graph, residual_graph_args,
+ viewbefore = conftest.option.view)
+ return insns, res
+
+
+class TestTimeshift(TimeshiftingTests):
+
+ def test_simple_fixed(self):
+ py.test.skip("green return not working")
+ def ll_function(x, y):
+ return hint(x + y, concrete=True)
+ insns, res = self.timeshift(ll_function, [5, 7])
+ assert res == 12
+ assert insns == {}
+
+ def test_very_simple(self):
+ def ll_function(x, y):
+ return x + y
+ insns, res = self.timeshift(ll_function, [5, 7])
+ assert res == 12
+ assert insns == {'int_add': 1}
+
+ def test_convert_const_to_redbox(self):
+ def ll_function(x, y):
+ x = hint(x, concrete=True)
+ tot = 0
+ while x: # conversion from green '0' to red 'tot'
+ tot += y
+ x -= 1
+ return tot
+ insns, res = self.timeshift(ll_function, [7, 2])
+ assert res == 14
+ assert insns == {'int_add': 7}
+
+ def test_simple_opt_const_propagation2(self):
+ def ll_function(x, y):
+ return x + y
+ insns, res = self.timeshift(ll_function, [5, 7], [0, 1])
+ assert res == 12
+ assert insns == {}
+
+ def test_simple_opt_const_propagation1(self):
+ def ll_function(x):
+ return -x
+ insns, res = self.timeshift(ll_function, [5], [0])
+ assert res == -5
+ assert insns == {}
+
+ def test_loop_folding(self):
+ def ll_function(x, y):
+ tot = 0
+ x = hint(x, concrete=True)
+ while x:
+ tot += y
+ x -= 1
+ return tot
+ insns, res = self.timeshift(ll_function, [7, 2], [0, 1])
+ assert res == 14
+ assert insns == {}
+
+ def test_loop_merging(self):
+ def ll_function(x, y):
+ tot = 0
+ while x:
+ tot += y
+ x -= 1
+ return tot
+ insns, res = self.timeshift(ll_function, [7, 2], [])
+ assert res == 14
+ assert insns['int_add'] == 2
+ assert insns['int_is_true'] == 2
+
+ insns, res = self.timeshift(ll_function, [7, 2], [0])
+ assert res == 14
+ assert insns['int_add'] == 2
+ assert insns['int_is_true'] == 1
+
+ insns, res = self.timeshift(ll_function, [7, 2], [1])
+ assert res == 14
+ assert insns['int_add'] == 1
+ assert insns['int_is_true'] == 2
+
+ insns, res = self.timeshift(ll_function, [7, 2], [0, 1])
+ assert res == 14
+ assert insns['int_add'] == 1
+ assert insns['int_is_true'] == 1
+
+ def test_two_loops_merging(self):
+ def ll_function(x, y):
+ tot = 0
+ while x:
+ tot += y
+ x -= 1
+ while y:
+ tot += y
+ y -= 1
+ return tot
+ insns, res = self.timeshift(ll_function, [7, 3], [])
+ assert res == 27
+ assert insns['int_add'] == 3
+ assert insns['int_is_true'] == 3
+
+ def test_convert_greenvar_to_redvar(self):
+ def ll_function(x, y):
+ hint(x, concrete=True)
+ return x - y
+ insns, res = self.timeshift(ll_function, [70, 4], [0])
+ assert res == 66
+ assert insns['int_sub'] == 1
+ insns, res = self.timeshift(ll_function, [70, 4], [0, 1])
+ assert res == 66
+ assert insns == {}
+
+ def test_green_across_split(self):
+ def ll_function(x, y):
+ hint(x, concrete=True)
+ if y > 2:
+ z = x - y
+ else:
+ z = x + y
+ return z
+ insns, res = self.timeshift(ll_function, [70, 4], [0])
+ assert res == 66
+ assert insns['int_add'] == 1
+ assert insns['int_sub'] == 1
+
+ def test_merge_const_before_return(self):
+ def ll_function(x):
+ if x > 0:
+ y = 17
+ else:
+ y = 22
x -= 1
- return tot
- insns, res = timeshift(ll_function, [7, 2], [])
- assert res == 14
- assert insns['int_add'] == 2
- assert insns['int_is_true'] == 2
-
- insns, res = timeshift(ll_function, [7, 2], [0])
- assert res == 14
- assert insns['int_add'] == 2
- assert insns['int_is_true'] == 1
-
- insns, res = timeshift(ll_function, [7, 2], [1])
- assert res == 14
- assert insns['int_add'] == 1
- assert insns['int_is_true'] == 2
-
- insns, res = timeshift(ll_function, [7, 2], [0, 1])
- assert res == 14
- assert insns['int_add'] == 1
- assert insns['int_is_true'] == 1
-
-def test_two_loops_merging():
- def ll_function(x, y):
- tot = 0
- while x:
- tot += y
+ y += 1
+ return y+x
+ insns, res = self.timeshift(ll_function, [-70], [])
+ assert res == 23-71
+ assert insns == {'int_gt': 1, 'int_add': 2, 'int_sub': 2}
+
+ def test_merge_3_redconsts_before_return(self):
+ def ll_function(x):
+ if x > 2:
+ y = hint(54, variable=True)
+ elif x > 0:
+ y = hint(17, variable=True)
+ else:
+ y = hint(22, variable=True)
x -= 1
- while y:
- tot += y
- y -= 1
- return tot
- insns, res = timeshift(ll_function, [7, 3], [])
- assert res == 27
- assert insns['int_add'] == 3
- assert insns['int_is_true'] == 3
-
-def test_convert_greenvar_to_redvar():
- def ll_function(x, y):
- hint(x, concrete=True)
- return x - y
- insns, res = timeshift(ll_function, [70, 4], [0])
- assert res == 66
- assert insns['int_sub'] == 1
- insns, res = timeshift(ll_function, [70, 4], [0, 1])
- assert res == 66
- assert insns == {}
-
-def test_green_across_split():
- def ll_function(x, y):
- hint(x, concrete=True)
- if y > 2:
- z = x - y
- else:
- z = x + y
- return z
- insns, res = timeshift(ll_function, [70, 4], [0])
- assert res == 66
- assert insns['int_add'] == 1
- assert insns['int_sub'] == 1
-
-def test_merge_const_before_return():
- def ll_function(x):
- if x > 0:
- y = 17
- else:
- y = 22
- x -= 1
- y += 1
- return y+x
- insns, res = timeshift(ll_function, [-70], [])
- assert res == 23-71
- assert insns == {'int_gt': 1, 'int_add': 2, 'int_sub': 2}
-
-def test_merge_3_redconsts_before_return():
- def ll_function(x):
- if x > 2:
- y = hint(54, variable=True)
- elif x > 0:
- y = hint(17, variable=True)
- else:
- y = hint(22, variable=True)
- x -= 1
- y += 1
- return y+x
- insns, res = timeshift(ll_function, [-70], [])
- assert res == ll_function(-70)
- insns, res = timeshift(ll_function, [1], [])
- assert res == ll_function(1)
- insns, res = timeshift(ll_function, [-70], [])
- assert res == ll_function(-70)
-
-def test_merge_const_at_return():
- py.test.skip("green return")
- def ll_function(x):
- if x > 0:
- return 17
- else:
- return 22
- insns, res = timeshift(ll_function, [-70], [])
- assert res == 22
- assert insns == {'int_gt': 1}
-
-def test_arith_plus_minus():
- def ll_plus_minus(encoded_insn, nb_insn, x, y):
- acc = x
- pc = 0
- while pc < nb_insn:
- op = (encoded_insn >> (pc*4)) & 0xF
- op = hint(op, concrete=True)
- if op == 0xA:
- acc += y
- elif op == 0x5:
- acc -= y
- pc += 1
- return acc
- assert ll_plus_minus(0xA5A, 3, 32, 10) == 42
- insns, res = timeshift(ll_plus_minus, [0xA5A, 3, 32, 10], [0, 1])
- assert res == 42
- assert insns == {'int_add': 2,
- 'int_sub': 1}
-
-def test_simple_struct():
- S = lltype.GcStruct('helloworld', ('hello', lltype.Signed),
- ('world', lltype.Signed),
- hints={'immutable': True})
- def ll_function(s):
- return s.hello * s.world
- s1 = lltype.malloc(S)
- s1.hello = 6
- s1.world = 7
- insns, res = timeshift(ll_function, [s1], [])
- assert res == 42
- assert insns == {'getfield': 2,
- 'int_mul': 1}
- insns, res = timeshift(ll_function, [s1], [0])
- assert res == 42
- assert insns == {}
-
-def test_simple_array():
- A = lltype.GcArray(lltype.Signed,
- hints={'immutable': True})
- def ll_function(a):
- return a[0] * a[1]
- a1 = lltype.malloc(A, 2)
- a1[0] = 6
- a1[1] = 7
- insns, res = timeshift(ll_function, [a1], [])
- assert res == 42
- assert insns == {'getarrayitem': 2,
- 'int_mul': 1}
- insns, res = timeshift(ll_function, [a1], [0])
- assert res == 42
- assert insns == {}
-
-def test_simple_struct_malloc():
- py.test.skip("blue containers: to be reimplemented")
- S = lltype.GcStruct('helloworld', ('hello', lltype.Signed),
- ('world', lltype.Signed))
- def ll_function(x):
- s = lltype.malloc(S)
- s.hello = x
- return s.hello + s.world
-
- insns, res = timeshift(ll_function, [3], [])
- assert res == 3
- assert insns == {'int_add': 1}
-
- insns, res = timeshift(ll_function, [3], [0])
- assert res == 3
- assert insns == {}
-
-def test_inlined_substructure():
- py.test.skip("blue containers: to be reimplemented")
- S = lltype.Struct('S', ('n', lltype.Signed))
- T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
- def ll_function(k):
- t = lltype.malloc(T)
- t.s.n = k
- l = t.s.n
- return l
- insns, res = timeshift(ll_function, [7], [])
- assert res == 7
- assert insns == {}
-
- insns, res = timeshift(ll_function, [7], [0])
- assert res == 7
- assert insns == {}
-
-def test_degenerated_before_return():
- S = lltype.GcStruct('S', ('n', lltype.Signed))
- T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
-
- def ll_function(flag):
- t = lltype.malloc(T)
- t.s.n = 3
- s = lltype.malloc(S)
- s.n = 4
- if flag:
- s = t.s
- s.n += 1
- return s.n * t.s.n
- insns, res = timeshift(ll_function, [0], [])
- assert res == 5 * 3
- insns, res = timeshift(ll_function, [1], [])
- assert res == 4 * 4
-
-def test_degenerated_before_return_2():
- S = lltype.GcStruct('S', ('n', lltype.Signed))
- T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
-
- def ll_function(flag):
- t = lltype.malloc(T)
- t.s.n = 3
- s = lltype.malloc(S)
- s.n = 4
- if flag:
- pass
- else:
- s = t.s
- s.n += 1
- return s.n * t.s.n
- insns, res = timeshift(ll_function, [1], [])
- assert res == 5 * 3
- insns, res = timeshift(ll_function, [0], [])
- assert res == 4 * 4
-
-def test_degenerated_at_return():
- S = lltype.GcStruct('S', ('n', lltype.Signed))
- T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
-
- def ll_function(flag):
- t = lltype.malloc(T)
- t.n = 3.25
- t.s.n = 3
- s = lltype.malloc(S)
- s.n = 4
- if flag:
- s = t.s
- return s
- insns, res = timeshift(ll_function, [0], [])
- assert res.n == 4
- assert lltype.parentlink(res._obj) == (None, None)
- insns, res = timeshift(ll_function, [1], [])
- assert res.n == 3
- parent, parentindex = lltype.parentlink(res._obj)
- assert parentindex == 's'
- assert parent.n == 3.25
-
-def test_degenerated_via_substructure():
- S = lltype.GcStruct('S', ('n', lltype.Signed))
- T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
-
- def ll_function(flag):
- t = lltype.malloc(T)
- t.s.n = 3
- s = lltype.malloc(S)
- s.n = 7
- if flag:
- pass
- else:
- s = t.s
- t.s.n += 1
- return s.n * t.s.n
- insns, res = timeshift(ll_function, [1], [])
- assert res == 7 * 4
- insns, res = timeshift(ll_function, [0], [])
- assert res == 4 * 4
-
-def test_plus_minus_all_inlined():
- def ll_plus_minus(s, x, y):
- acc = x
- n = len(s)
- pc = 0
- while pc < n:
- op = s[pc]
- op = hint(op, concrete=True)
- if op == '+':
- acc += y
- elif op == '-':
- acc -= y
- pc += 1
- return acc
- s = rstr.string_repr.convert_const("+-+")
- insns, res = timeshift(ll_plus_minus, [s, 0, 2], [0], inline=999)
- assert res == ll_plus_minus("+-+", 0, 2)
- assert insns == {'int_add': 2, 'int_sub': 1}
-
-def test_red_virtual_container():
- # this checks that red boxes are able to be virtualized dynamically by
- # the compiler (the P_NOVIRTUAL policy prevents the hint-annotator from
- # marking variables in blue)
- S = lltype.GcStruct('S', ('n', lltype.Signed))
- def ll_function(n):
- s = lltype.malloc(S)
- s.n = n
- return s.n
- insns, res = timeshift(ll_function, [42], [], policy=P_NOVIRTUAL)
- assert res == 42
- assert insns == {}
-
-def test_red_propagate():
- S = lltype.GcStruct('S', ('n', lltype.Signed))
- def ll_function(n, k):
- s = lltype.malloc(S)
- s.n = n
- if k < 0:
- return -123
- return s.n * k
- insns, res = timeshift(ll_function, [3, 8], [], policy=P_NOVIRTUAL)
- assert res == 24
- assert insns == {'int_lt': 1, 'int_mul': 1}
-
-def test_red_subcontainer():
- S = lltype.Struct('S', ('n', lltype.Signed))
- T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
- def ll_function(k):
- t = lltype.malloc(T)
- s = t.s
- s.n = k
- if k < 0:
- return -123
- result = s.n * (k-1)
- keepalive_until_here(t)
- return result
- insns, res = timeshift(ll_function, [7], [], policy=P_NOVIRTUAL)
- assert res == 42
- assert insns == {'int_lt': 1, 'int_mul': 1, 'int_sub': 1}
-
-def test_merge_structures():
- S = lltype.GcStruct('S', ('n', lltype.Signed))
- T = lltype.GcStruct('T', ('s', lltype.Ptr(S)), ('n', lltype.Signed))
+ y += 1
+ return y+x
+ insns, res = self.timeshift(ll_function, [-70], [])
+ assert res == ll_function(-70)
+ insns, res = self.timeshift(ll_function, [1], [])
+ assert res == ll_function(1)
+ insns, res = self.timeshift(ll_function, [-70], [])
+ assert res == ll_function(-70)
+
+ def test_merge_const_at_return(self):
+ py.test.skip("green return")
+ def ll_function(x):
+ if x > 0:
+ return 17
+ else:
+ return 22
+ insns, res = self.timeshift(ll_function, [-70], [])
+ assert res == 22
+ assert insns == {'int_gt': 1}
+
+ def test_arith_plus_minus(self):
+ def ll_plus_minus(encoded_insn, nb_insn, x, y):
+ acc = x
+ pc = 0
+ while pc < nb_insn:
+ op = (encoded_insn >> (pc*4)) & 0xF
+ op = hint(op, concrete=True)
+ if op == 0xA:
+ acc += y
+ elif op == 0x5:
+ acc -= y
+ pc += 1
+ return acc
+ assert ll_plus_minus(0xA5A, 3, 32, 10) == 42
+ insns, res = self.timeshift(ll_plus_minus, [0xA5A, 3, 32, 10], [0, 1])
+ assert res == 42
+ assert insns == {'int_add': 2,
+ 'int_sub': 1}
+
+ def test_simple_struct(self):
+ S = lltype.GcStruct('helloworld', ('hello', lltype.Signed),
+ ('world', lltype.Signed),
+ hints={'immutable': True})
+ def ll_function(s):
+ return s.hello * s.world
+ s1 = lltype.malloc(S)
+ s1.hello = 6
+ s1.world = 7
+ insns, res = self.timeshift(ll_function, [s1], [])
+ assert res == 42
+ assert insns == {'getfield': 2,
+ 'int_mul': 1}
+ insns, res = self.timeshift(ll_function, [s1], [0])
+ assert res == 42
+ assert insns == {}
+
+ def test_simple_array(self):
+ A = lltype.GcArray(lltype.Signed,
+ hints={'immutable': True})
+ def ll_function(a):
+ return a[0] * a[1]
+ a1 = lltype.malloc(A, 2)
+ a1[0] = 6
+ a1[1] = 7
+ insns, res = self.timeshift(ll_function, [a1], [])
+ assert res == 42
+ assert insns == {'getarrayitem': 2,
+ 'int_mul': 1}
+ insns, res = self.timeshift(ll_function, [a1], [0])
+ assert res == 42
+ assert insns == {}
+
+ def test_simple_struct_malloc(self):
+ py.test.skip("blue containers: to be reimplemented")
+ S = lltype.GcStruct('helloworld', ('hello', lltype.Signed),
+ ('world', lltype.Signed))
+ def ll_function(x):
+ s = lltype.malloc(S)
+ s.hello = x
+ return s.hello + s.world
- def ll_function(flag):
- if flag:
+ insns, res = self.timeshift(ll_function, [3], [])
+ assert res == 3
+ assert insns == {'int_add': 1}
+
+ insns, res = self.timeshift(ll_function, [3], [0])
+ assert res == 3
+ assert insns == {}
+
+ def test_inlined_substructure(self):
+ py.test.skip("blue containers: to be reimplemented")
+ S = lltype.Struct('S', ('n', lltype.Signed))
+ T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
+ def ll_function(k):
+ t = lltype.malloc(T)
+ t.s.n = k
+ l = t.s.n
+ return l
+ insns, res = self.timeshift(ll_function, [7], [])
+ assert res == 7
+ assert insns == {}
+
+ insns, res = self.timeshift(ll_function, [7], [0])
+ assert res == 7
+ assert insns == {}
+
+ def test_degenerated_before_return(self):
+ S = lltype.GcStruct('S', ('n', lltype.Signed))
+ T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
+
+ def ll_function(flag):
+ t = lltype.malloc(T)
+ t.s.n = 3
s = lltype.malloc(S)
- s.n = 1
+ s.n = 4
+ if flag:
+ s = t.s
+ s.n += 1
+ return s.n * t.s.n
+ insns, res = self.timeshift(ll_function, [0], [])
+ assert res == 5 * 3
+ insns, res = self.timeshift(ll_function, [1], [])
+ assert res == 4 * 4
+
+ def test_degenerated_before_return_2(self):
+ S = lltype.GcStruct('S', ('n', lltype.Signed))
+ T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
+
+ def ll_function(flag):
t = lltype.malloc(T)
- t.s = s
- t.n = 2
- else:
+ t.s.n = 3
s = lltype.malloc(S)
- s.n = 5
+ s.n = 4
+ if flag:
+ pass
+ else:
+ s = t.s
+ s.n += 1
+ return s.n * t.s.n
+ insns, res = self.timeshift(ll_function, [1], [])
+ assert res == 5 * 3
+ insns, res = self.timeshift(ll_function, [0], [])
+ assert res == 4 * 4
+
+ def test_degenerated_at_return(self):
+ S = lltype.GcStruct('S', ('n', lltype.Signed))
+ T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
+
+ def ll_function(flag):
t = lltype.malloc(T)
- t.s = s
- t.n = 6
- return t.n + t.s.n
- insns, res = timeshift(ll_function, [0], [], policy=P_NOVIRTUAL)
- assert res == 5 + 6
- assert insns == {'int_is_true': 1, 'int_add': 1}
- insns, res = timeshift(ll_function, [1], [], policy=P_NOVIRTUAL)
- assert res == 1 + 2
- assert insns == {'int_is_true': 1, 'int_add': 1}
-
-def test_call_simple():
- def ll_add_one(x):
- return x + 1
- def ll_function(y):
- return ll_add_one(y)
- insns, res = timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
- assert res == 6
- assert insns == {'int_add': 1}
-
-def test_call_2():
- def ll_add_one(x):
- return x + 1
- def ll_function(y):
- return ll_add_one(y) + y
- insns, res = timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
- assert res == 11
- assert insns == {'int_add': 2}
-
-def test_call_3():
- def ll_add_one(x):
- return x + 1
- def ll_two(x):
- return ll_add_one(ll_add_one(x)) - x
- def ll_function(y):
- return ll_two(y) * y
- insns, res = timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
- assert res == 10
- assert insns == {'int_add': 2, 'int_sub': 1, 'int_mul': 1}
+ t.n = 3.25
+ t.s.n = 3
+ s = lltype.malloc(S)
+ s.n = 4
+ if flag:
+ s = t.s
+ return s
+ insns, res = self.timeshift(ll_function, [0], [])
+ assert res.n == 4
+ assert lltype.parentlink(res._obj) == (None, None)
+ insns, res = self.timeshift(ll_function, [1], [])
+ assert res.n == 3
+ parent, parentindex = lltype.parentlink(res._obj)
+ assert parentindex == 's'
+ assert parent.n == 3.25
+
+ def test_degenerated_via_substructure(self):
+ S = lltype.GcStruct('S', ('n', lltype.Signed))
+ T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
+
+ def ll_function(flag):
+ t = lltype.malloc(T)
+ t.s.n = 3
+ s = lltype.malloc(S)
+ s.n = 7
+ if flag:
+ pass
+ else:
+ s = t.s
+ t.s.n += 1
+ return s.n * t.s.n
+ insns, res = self.timeshift(ll_function, [1], [])
+ assert res == 7 * 4
+ insns, res = self.timeshift(ll_function, [0], [])
+ assert res == 4 * 4
+
+ def test_plus_minus_all_inlined(self):
+ def ll_plus_minus(s, x, y):
+ acc = x
+ n = len(s)
+ pc = 0
+ while pc < n:
+ op = s[pc]
+ op = hint(op, concrete=True)
+ if op == '+':
+ acc += y
+ elif op == '-':
+ acc -= y
+ pc += 1
+ return acc
+ s = rstr.string_repr.convert_const("+-+")
+ insns, res = self.timeshift(ll_plus_minus, [s, 0, 2], [0], inline=999)
+ assert res == ll_plus_minus("+-+", 0, 2)
+ assert insns == {'int_add': 2, 'int_sub': 1}
+
+ def test_red_virtual_container(self):
+ # this checks that red boxes are able to be virtualized dynamically by
+ # the compiler (the P_NOVIRTUAL policy prevents the hint-annotator from
+ # marking variables in blue)
+ S = lltype.GcStruct('S', ('n', lltype.Signed))
+ def ll_function(n):
+ s = lltype.malloc(S)
+ s.n = n
+ return s.n
+ insns, res = self.timeshift(ll_function, [42], [], policy=P_NOVIRTUAL)
+ assert res == 42
+ assert insns == {}
+
+ def test_red_propagate(self):
+ S = lltype.GcStruct('S', ('n', lltype.Signed))
+ def ll_function(n, k):
+ s = lltype.malloc(S)
+ s.n = n
+ if k < 0:
+ return -123
+ return s.n * k
+ insns, res = self.timeshift(ll_function, [3, 8], [], policy=P_NOVIRTUAL)
+ assert res == 24
+ assert insns == {'int_lt': 1, 'int_mul': 1}
+
+ def test_red_subcontainer(self):
+ S = lltype.Struct('S', ('n', lltype.Signed))
+ T = lltype.GcStruct('T', ('s', S), ('n', lltype.Float))
+ def ll_function(k):
+ t = lltype.malloc(T)
+ s = t.s
+ s.n = k
+ if k < 0:
+ return -123
+ result = s.n * (k-1)
+ keepalive_until_here(t)
+ return result
+ insns, res = self.timeshift(ll_function, [7], [], policy=P_NOVIRTUAL)
+ assert res == 42
+ assert insns == {'int_lt': 1, 'int_mul': 1, 'int_sub': 1}
+
+ def test_merge_structures(self):
+ S = lltype.GcStruct('S', ('n', lltype.Signed))
+ T = lltype.GcStruct('T', ('s', lltype.Ptr(S)), ('n', lltype.Signed))
+
+ def ll_function(flag):
+ if flag:
+ s = lltype.malloc(S)
+ s.n = 1
+ t = lltype.malloc(T)
+ t.s = s
+ t.n = 2
+ else:
+ s = lltype.malloc(S)
+ s.n = 5
+ t = lltype.malloc(T)
+ t.s = s
+ t.n = 6
+ return t.n + t.s.n
+ insns, res = self.timeshift(ll_function, [0], [], policy=P_NOVIRTUAL)
+ assert res == 5 + 6
+ assert insns == {'int_is_true': 1, 'int_add': 1}
+ insns, res = self.timeshift(ll_function, [1], [], policy=P_NOVIRTUAL)
+ assert res == 1 + 2
+ assert insns == {'int_is_true': 1, 'int_add': 1}
+
+ def test_call_simple(self):
+ def ll_add_one(x):
+ return x + 1
+ def ll_function(y):
+ return ll_add_one(y)
+ insns, res = self.timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
+ assert res == 6
+ assert insns == {'int_add': 1}
+
+ def test_call_2(self):
+ def ll_add_one(x):
+ return x + 1
+ def ll_function(y):
+ return ll_add_one(y) + y
+ insns, res = self.timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
+ assert res == 11
+ assert insns == {'int_add': 2}
+
+ def test_call_3(self):
+ def ll_add_one(x):
+ return x + 1
+ def ll_two(x):
+ return ll_add_one(ll_add_one(x)) - x
+ def ll_function(y):
+ return ll_two(y) * y
+ insns, res = self.timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
+ assert res == 10
+ assert insns == {'int_add': 2, 'int_sub': 1, 'int_mul': 1}
Modified: pypy/dist/pypy/jit/timeshifter/test/test_tl.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_tl.py (original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_tl.py Wed Aug 23 18:47:27 2006
@@ -1,15 +1,18 @@
from pypy.rpython.lltypesystem.rstr import string_repr
-from pypy.jit.timeshifter.test.test_timeshift import timeshift
+from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests
from pypy.jit.timeshifter.test.test_vlist import P_OOPSPEC
from pypy.jit.tl import tl
from pypy.jit.tl.test.test_tl import FACTORIAL_SOURCE
-def test_tl():
- import py; py.test.skip("in-progress")
- code = tl.compile(FACTORIAL_SOURCE)
- ll_code = string_repr.convert_const(code)
- insns, res = timeshift(tl.interp_without_call, [ll_code, 0, 5], [0, 1],
- policy=P_OOPSPEC)
- assert res == 120
+class TestTL(TimeshiftingTests):
+
+ def test_tl(self):
+ import py; py.test.skip("in-progress")
+ code = tl.compile(FACTORIAL_SOURCE)
+ ll_code = string_repr.convert_const(code)
+ insns, res = self.timeshift(tl.interp_without_call,
+ [ll_code, 0, 5], [0, 1],
+ policy=P_OOPSPEC)
+ assert res == 120
Modified: pypy/dist/pypy/jit/timeshifter/test/test_tlr.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_tlr.py (original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_tlr.py Wed Aug 23 18:47:27 2006
@@ -1,11 +1,14 @@
from pypy.rpython.lltypesystem.rstr import string_repr
-from pypy.jit.timeshifter.test.test_timeshift import timeshift
+from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests
from pypy.jit.timeshifter.test.test_vlist import P_OOPSPEC
from pypy.jit.tl import tlr
-def test_tlr():
- bytecode = string_repr.convert_const(tlr.SQUARE)
- insns, res = timeshift(tlr.interpret, [bytecode, 9], [0], policy=P_OOPSPEC)
- assert res == 81
+class TestTLR(TimeshiftingTests):
+
+ def test_tlr(self):
+ bytecode = string_repr.convert_const(tlr.SQUARE)
+ insns, res = self.timeshift(tlr.interpret, [bytecode, 9], [0],
+ policy=P_OOPSPEC)
+ assert res == 81
Modified: pypy/dist/pypy/jit/timeshifter/test/test_vlist.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_vlist.py (original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_vlist.py Wed Aug 23 18:47:27 2006
@@ -1,74 +1,76 @@
from pypy.annotation.policy import AnnotatorPolicy
-from pypy.jit.timeshifter.test.test_timeshift import timeshift
+from pypy.jit.timeshifter.test.test_timeshift import TimeshiftingTests
P_OOPSPEC = AnnotatorPolicy()
P_OOPSPEC.novirtualcontainer = True
P_OOPSPEC.oopspec = True
-def test_vlist():
- def ll_function():
- lst = []
- lst.append(12)
- return lst[0]
- insns, res = timeshift(ll_function, [], [], policy=P_OOPSPEC)
- assert res == 12
- assert insns == {}
-
-def test_enter_block():
- def ll_function(flag):
- lst = []
- lst.append(flag)
- lst.append(131)
- if flag:
+class TestVList(TimeshiftingTests):
+
+ def test_vlist(self):
+ def ll_function():
+ lst = []
+ lst.append(12)
return lst[0]
- else:
- return lst[1]
- insns, res = timeshift(ll_function, [6], [], policy=P_OOPSPEC)
- assert res == 6
- assert insns == {'int_is_true': 1}
- insns, res = timeshift(ll_function, [0], [], policy=P_OOPSPEC)
- assert res == 131
- assert insns == {'int_is_true': 1}
-
-def test_merge():
- def ll_function(flag):
- lst = []
- if flag:
+ insns, res = self.timeshift(ll_function, [], [], policy=P_OOPSPEC)
+ assert res == 12
+ assert insns == {}
+
+ def test_enter_block(self):
+ def ll_function(flag):
+ lst = []
lst.append(flag)
- else:
lst.append(131)
- return lst[-1]
- insns, res = timeshift(ll_function, [6], [], policy=P_OOPSPEC)
- assert res == 6
- assert insns == {'int_is_true': 1}
- insns, res = timeshift(ll_function, [0], [], policy=P_OOPSPEC)
- assert res == 131
- assert insns == {'int_is_true': 1}
-
-def test_replace():
- def ll_function(flag):
- lst = []
- if flag:
- lst.append(12)
- else:
- lst.append(131)
- return lst[-1]
- insns, res = timeshift(ll_function, [6], [], policy=P_OOPSPEC)
- assert res == 12
- assert insns == {'int_is_true': 1}
- insns, res = timeshift(ll_function, [0], [], policy=P_OOPSPEC)
- assert res == 131
- assert insns == {'int_is_true': 1}
-
-def test_force():
- def ll_function(n):
- lst = []
- lst.append(n)
- if n:
- lst.append(12)
- return lst[-1]
- insns, res = timeshift(ll_function, [6], [], policy=P_OOPSPEC)
- assert res == 12
- insns, res = timeshift(ll_function, [0], [], policy=P_OOPSPEC)
- assert res == 0
+ if flag:
+ return lst[0]
+ else:
+ return lst[1]
+ insns, res = self.timeshift(ll_function, [6], [], policy=P_OOPSPEC)
+ assert res == 6
+ assert insns == {'int_is_true': 1}
+ insns, res = self.timeshift(ll_function, [0], [], policy=P_OOPSPEC)
+ assert res == 131
+ assert insns == {'int_is_true': 1}
+
+ def test_merge(self):
+ def ll_function(flag):
+ lst = []
+ if flag:
+ lst.append(flag)
+ else:
+ lst.append(131)
+ return lst[-1]
+ insns, res = self.timeshift(ll_function, [6], [], policy=P_OOPSPEC)
+ assert res == 6
+ assert insns == {'int_is_true': 1}
+ insns, res = self.timeshift(ll_function, [0], [], policy=P_OOPSPEC)
+ assert res == 131
+ assert insns == {'int_is_true': 1}
+
+ def test_replace(self):
+ def ll_function(flag):
+ lst = []
+ if flag:
+ lst.append(12)
+ else:
+ lst.append(131)
+ return lst[-1]
+ insns, res = self.timeshift(ll_function, [6], [], policy=P_OOPSPEC)
+ assert res == 12
+ assert insns == {'int_is_true': 1}
+ insns, res = self.timeshift(ll_function, [0], [], policy=P_OOPSPEC)
+ assert res == 131
+ assert insns == {'int_is_true': 1}
+
+ def test_force(self):
+ def ll_function(n):
+ lst = []
+ lst.append(n)
+ if n:
+ lst.append(12)
+ return lst[-1]
+ insns, res = self.timeshift(ll_function, [6], [], policy=P_OOPSPEC)
+ assert res == 12
+ insns, res = self.timeshift(ll_function, [0], [], policy=P_OOPSPEC)
+ assert res == 0
Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/timeshift.py (original)
+++ pypy/dist/pypy/jit/timeshifter/timeshift.py Wed Aug 23 18:47:27 2006
@@ -1,25 +1,27 @@
-import py
+import py, types
from pypy.rpython.lltypesystem import lltype
from pypy.objspace.flow import model as flowmodel
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.rpython import rmodel, rgenop, annlowlevel
+from pypy.rpython import rmodel, annlowlevel
from pypy.rpython.lltypesystem import rtuple, rlist, rdict
from pypy.jit.timeshifter import rtimeshift
from pypy.jit.timeshifter.rtyper import HintRTyper, originalconcretetype
from pypy.jit.timeshifter.rtyper import GreenRepr, RedRepr, HintLowLevelOpList
from pypy.translator.unsimplify import varoftype, copyvar
from pypy.translator.backendopt import support
+from pypy.jit.codegen import model as cgmodel
# ___________________________________________________________
class HintTimeshift(object):
- def __init__(self, hannotator, rtyper):
+ def __init__(self, hannotator, rtyper, RGenOp):
self.hannotator = hannotator
self.rtyper = rtyper
+ self.RGenOp = RGenOp
self.hrtyper = HintRTyper(hannotator, self)
self.latestexitindex = -1
self.annhelper = annlowlevel.MixLevelHelperAnnotator(rtyper)
@@ -29,6 +31,9 @@
self.s_RedBox, self.r_RedBox = self.s_r_instanceof(rvalue.RedBox)
self.s_OopSpecDesc, self.r_OopSpecDesc = self.s_r_instanceof(
oop.OopSpecDesc)
+ self.s_ConstOrVar, self.r_ConstOrVar = self.s_r_instanceof(
+ cgmodel.GenVarOrConst)
+ self.s_Block, self.r_Block = self.s_r_instanceof(cgmodel.CodeGenBlock)
getrepr = self.rtyper.getrepr
@@ -46,29 +51,33 @@
self.r_box_accum = getrepr(self.s_box_accum)
self.r_box_accum.setup()
+ def ll_make_builder():
+ rgenop = RGenOp.get_rgenop_for_testing()
+ return rtimeshift.make_builder(rgenop)
+
self.ll_make_builder_graph = self.annhelper.getgraph(
- rtimeshift.ll_make_builder,
+ ll_make_builder,
[], self.s_ResidualGraphBuilder)
self.ll_int_box_graph = self.annhelper.getgraph(
rtimeshift.ll_int_box,
- [rgenop.s_ConstOrVar, rgenop.s_ConstOrVar],
+ [self.s_ConstOrVar, self.s_ConstOrVar],
self.s_RedBox)
self.ll_addr_box_graph = self.annhelper.getgraph(
rtimeshift.ll_addr_box,
- [rgenop.s_ConstOrVar, rgenop.s_ConstOrVar],
+ [self.s_ConstOrVar, self.s_ConstOrVar],
self.s_RedBox)
self.ll_double_box_graph = self.annhelper.getgraph(
rtimeshift.ll_int_box,
- [rgenop.s_ConstOrVar, rgenop.s_ConstOrVar],
+ [self.s_ConstOrVar, self.s_ConstOrVar],
self.s_RedBox)
self.ll_geninputarg_graph = self.annhelper.getgraph(
rtimeshift.ll_geninputarg,
- [self.s_ResidualGraphBuilder, annmodel.SomePtr(rgenop.CONSTORVAR)],
- rgenop.s_ConstOrVar)
+ [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],
- annmodel.SomePtr(rgenop.BLOCK))
+ self.s_Block)
## self.ll_close_jitstate_graph = self.annhelper.getgraph(
## rtimeshift.ll_close_jitstate,
@@ -266,10 +275,12 @@
newblock.closeblock(bridge)
return newblock
- def make_const_box(self, llops, r_green, v_value):
+ def make_const_box(self, llops, r_green, v_value, v_jitstate):
v_box = llops.genmixlevelhelpercall(
rvalue.ll_fromvalue,
- [r_green.annotation()], [v_value], self.s_RedBox)
+ [self.s_JITState, r_green.annotation()],
+ [v_jitstate, v_value],
+ self.s_RedBox)
return v_box
@@ -566,6 +577,7 @@
[v_res],
v_newjitstate))
else:
+ v_jitstate = rename(orig_v_jitstate)
args_r = []
boxes_v = []
for var in inputargs[1:]:
@@ -574,7 +586,7 @@
if isinstance(r, RedRepr):
boxes_v.append(var)
elif isinstance(r, GreenRepr):
- v_box = self.make_const_box(llops, r, var)
+ v_box = self.make_const_box(llops, r, var, v_jitstate)
boxes_v.append(v_box)
else:
raise RuntimeError('Unsupported boxtype')
@@ -583,7 +595,6 @@
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)
c_exitindex = rmodel.inputconst(lltype.Signed, exitindex)
- v_jitstate = rename(orig_v_jitstate)
v_res = llops.genmixlevelhelpercall(rtimeshift.leave_block_split,
[self.s_JITState,
self.s_RedBox,
@@ -665,9 +676,10 @@
return_cache = self.return_cache
assert return_cache is not None
RETURN_TYPE = self.r_returnvalue.original_concretetype
+ gv_RETURN_TYPE = self.RGenOp.constTYPE(RETURN_TYPE)
def prepare_return(jitstate):
return rtimeshift.prepare_return(jitstate, return_cache,
- rgenop.constTYPE(RETURN_TYPE))
+ gv_RETURN_TYPE)
llops = HintLowLevelOpList(self, None)
v_return_builder = llops.genmixlevelhelpercall(prepare_return,
[self.s_JITState], [v_jitstate2],
Modified: pypy/dist/pypy/jit/timeshifter/vlist.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/vlist.py (original)
+++ pypy/dist/pypy/jit/timeshifter/vlist.py Wed Aug 23 18:47:27 2006
@@ -1,5 +1,4 @@
from pypy.rpython.lltypesystem import lltype
-from pypy.rpython import rgenop
from pypy.jit.timeshifter.rcontainer import AbstractContainer, cachedtype
from pypy.jit.timeshifter import rvalue
@@ -7,11 +6,11 @@
class ListTypeDesc(object):
__metaclass__ = cachedtype
- def __init__(self, LIST):
+ def __init__(self, RGenOp, LIST):
self.LIST = LIST
self.LISTPTR = lltype.Ptr(LIST)
- self.gv_type = rgenop.constTYPE(self.LIST)
- self.gv_ptrtype = rgenop.constTYPE(self.LISTPTR)
+ self.gv_type = RGenOp.constTYPE(self.LIST)
+ self.gv_ptrtype = RGenOp.constTYPE(self.LISTPTR)
self.build_newlist = LIST.list_builder.build_newlist
self.build_setitem = LIST.list_builder.build_setitem
Modified: pypy/dist/pypy/rpython/annlowlevel.py
==============================================================================
--- pypy/dist/pypy/rpython/annlowlevel.py (original)
+++ pypy/dist/pypy/rpython/annlowlevel.py Wed Aug 23 18:47:27 2006
@@ -50,7 +50,7 @@
def __init__(pol, rtyper=None):
pol.rtyper = rtyper
- def default_specialize(pol, funcdesc, args_s):
+ def default_specialize(funcdesc, args_s):
key = []
new_args_s = []
for s_obj in args_s:
@@ -69,6 +69,7 @@
flowgraph = funcdesc.cachedgraph(tuple(key))
args_s[:] = new_args_s
return flowgraph
+ default_specialize = staticmethod(default_specialize)
def override__init_opaque_object(pol, s_opaqueptr, s_value):
assert isinstance(s_opaqueptr, annmodel.SomePtr)
@@ -117,7 +118,8 @@
def default_specialize(pol, funcdesc, args_s):
name = funcdesc.name
if name.startswith('ll_') or name.startswith('_ll_'): # xxx can we do better?
- return LowLevelAnnotatorPolicy.default_specialize(pol, funcdesc, args_s)
+ return super(MixLevelAnnotatorPolicy, pol).default_specialize(
+ funcdesc, args_s)
else:
return funcdesc.cachedgraph(None)
Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Wed Aug 23 18:47:27 2006
@@ -969,6 +969,8 @@
if isinstance(self._T, (Array, FixedSizeArray)):
start, stop = self._obj.getbounds()
if not (start <= i < stop):
+ if isinstance(i, slice):
+ raise TypeError("array slicing not supported")
raise IndexError("array index out of bounds")
o = self._obj.getitem(i)
return _expose(o, self._solid)
@@ -986,6 +988,8 @@
" got %r" % (self._T, T1, T2))
start, stop = self._obj.getbounds()
if not (start <= i < stop):
+ if isinstance(i, slice):
+ raise TypeError("array slicing not supported")
raise IndexError("array index out of bounds")
self._obj.setitem(i, val)
return
Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Wed Aug 23 18:47:27 2006
@@ -779,11 +779,6 @@
return outof_cobject(v, r_to, llops)
# ____________________________________________________________
-
-def ll_both_none(ins1, ins2):
- return not ins1 and not ins2
-
-# ____________________________________________________________
#
# Low-level implementation of operations on classes and instances
@@ -836,3 +831,26 @@
else:
# type(None) -> NULL (for now)
return nullptr(typeOf(obj).TO.typeptr.TO)
+
+def ll_both_none(ins1, ins2):
+ return not ins1 and not ins2
+
+# ____________________________________________________________
+
+_missing = object()
+
+def fishllattr(inst, name, default=_missing):
+ p = widest = lltype.normalizeptr(inst)
+ while True:
+ try:
+ return getattr(p, 'inst_' + name)
+ except AttributeError:
+ pass
+ try:
+ p = p.super
+ except AttributeError:
+ break
+ if default is _missing:
+ raise AttributeError("%s has no field %s" % (lltype.typeOf(widest),
+ name))
+ return default
Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rlist.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/rlist.py Wed Aug 23 18:47:27 2006
@@ -122,7 +122,7 @@
c_LIST = llops.genvoidconst(LIST)
return llops.genop('direct_call',
[c_newlist, c_LIST, c_len],
- LISTPTR)
+ llops.constTYPE(LISTPTR))
def build_setitem(llops, v_list, index, v_item):
c_setitem_nonneg = llops.genconst(setitem_nonneg_ptr)
Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py (original)
+++ pypy/dist/pypy/rpython/rtyper.py Wed Aug 23 18:47:27 2006
@@ -897,6 +897,9 @@
def genvoidconst(self, placeholder):
return inputconst(Void, placeholder)
+ def constTYPE(self, T):
+ return T
+
# _______________________________________________________________________
# this has the side-effect of registering the unary and binary operations
# and the rtyper_chooserepr() methods
Modified: pypy/dist/pypy/rpython/test/test_rpbc.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rpbc.py (original)
+++ pypy/dist/pypy/rpython/test/test_rpbc.py Wed Aug 23 18:47:27 2006
@@ -428,6 +428,21 @@
res = self.interpret(f1, [2])
assert res == 6
+ def test_call_memo_with_string(self):
+ def memofn(s):
+ return eval(s)
+ memofn._annspecialcase_ = "specialize:memo"
+
+ def f1(i):
+ if i == 1:
+ return memofn("6*7")
+ else:
+ return memofn("1+2+3+4")
+ res = self.interpret(f1, [1])
+ assert res == 42
+ res = self.interpret(f1, [2])
+ assert res == 10
+
def test_rpbc_bound_method_static_call(self):
class R:
def meth(self):
More information about the Pypy-commit
mailing list