[pypy-svn] r33196 - in pypy/dist/pypy/jit/codegen/i386: . test
pedronis at codespeak.net
pedronis at codespeak.net
Wed Oct 11 23:34:25 CEST 2006
Author: pedronis
Date: Wed Oct 11 23:34:22 2006
New Revision: 33196
Modified:
pypy/dist/pypy/jit/codegen/i386/rgenop.py
pypy/dist/pypy/jit/codegen/i386/test/test_genc_promotion.py
pypy/dist/pypy/jit/codegen/i386/test/test_rgenop.py
Log:
support allocating new space and using it when a flexswitch runs out of allocated space for
its instructions.
all test_promotion tests now pass for the i386 backend!
Modified: pypy/dist/pypy/jit/codegen/i386/rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/rgenop.py (original)
+++ pypy/dist/pypy/jit/codegen/i386/rgenop.py Wed Oct 11 23:34:22 2006
@@ -2,7 +2,7 @@
from pypy.rpython.objectmodel import specialize
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.jit.codegen.i386.ri386 import *
-from pypy.jit.codegen.i386.codebuf import InMemoryCodeBuilder
+from pypy.jit.codegen.i386.codebuf import InMemoryCodeBuilder, CodeBlockOverflow
from pypy.jit.codegen.model import AbstractRGenOp, CodeGenBlock, CodeGenerator
from pypy.jit.codegen.model import GenVar, GenConst, CodeGenSwitch
from pypy.rpython import objectmodel
@@ -152,32 +152,58 @@
self.default_case_addr = 0
def initialize(self, builder, gv_exitswitch):
- RESERVED = 11*8+5 # XXX quite a lot for now :-/
mc = builder.mc
mc.MOV(eax, gv_exitswitch.operand(builder))
self.saved_state = builder._save_state()
+ self._reserve(mc)
+
+ def _reserve(self, mc):
+ RESERVED = 11*4+5 # XXX quite a lot for now :-/
pos = mc.tell()
mc.UD2()
mc.write('\x00' * (RESERVED-1))
self.nextfreepos = pos
self.endfreepos = pos + RESERVED
+ def _reserve_more(self):
+ start = self.nextfreepos
+ end = self.endfreepos
+ newmc = self.rgenop.open_mc()
+ self._reserve(newmc)
+ self.rgenop.close_mc(newmc)
+ fullmc = InMemoryCodeBuilder(start, end)
+ fullmc.JMP(rel32(self.nextfreepos))
+ fullmc.done()
+
def add_case(self, gv_case):
rgenop = self.rgenop
targetbuilder = Builder._new_from_state(rgenop, self.saved_state)
+ target_addr = targetbuilder.mc.tell()
+ try:
+ self._add_case(gv_case, target_addr)
+ except CodeBlockOverflow:
+ self._reserve_more()
+ self._add_case(gv_case, target_addr)
+ return targetbuilder
+
+ def _add_case(self, gv_case, target_addr):
start = self.nextfreepos
end = self.endfreepos
mc = InMemoryCodeBuilder(start, end)
mc.CMP(eax, gv_case.operand(None))
- mc.JE(rel32(targetbuilder.mc.tell()))
+ mc.JE(rel32(target_addr))
pos = mc.tell()
if self.default_case_addr:
mc.JMP(rel32(self.default_case_addr))
else:
+ illegal_start = mc.tell()
+ mc.JMP(rel32(0))
+ ud2_addr = mc.tell()
mc.UD2()
+ illegal_mc = InMemoryCodeBuilder(illegal_start, end)
+ illegal_mc.JMP(rel32(ud2_addr))
mc.done()
self.nextfreepos = pos
- return targetbuilder
def add_default(self):
rgenop = self.rgenop
@@ -190,7 +216,6 @@
mc.done()
return targetbuilder
-
class Builder(CodeGenerator):
def __init__(self, rgenop, mc, stackdepth):
Modified: pypy/dist/pypy/jit/codegen/i386/test/test_genc_promotion.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/test/test_genc_promotion.py (original)
+++ pypy/dist/pypy/jit/codegen/i386/test/test_genc_promotion.py Wed Oct 11 23:34:22 2006
@@ -7,6 +7,4 @@
# for the individual tests see
# ====> ../../../timeshifter/test/test_promotion.py
-
- def test_many_promotions(self):
- py.test.skip("in-progress")
+ pass
Modified: pypy/dist/pypy/jit/codegen/i386/test/test_rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/i386/test/test_rgenop.py (original)
+++ pypy/dist/pypy/jit/codegen/i386/test/test_rgenop.py Wed Oct 11 23:34:22 2006
@@ -390,3 +390,84 @@
assert res == 38
res = fn(42, 18)
assert res == 18
+
+def build_large_switch(rgenop):
+ """
+ def f(v0, v1):
+ if v0 == 0: # switch
+ return 21*v1
+ elif v0 == 1:
+ return 2+v1
+ elif v0 == 2:
+ return 4+v1
+ ...
+ elif v0 == 10:
+ return 2**10+v1
+ else:
+ return v1
+ """
+ signed_tok = rgenop.kindToken(lltype.Signed)
+ f2_token = rgenop.sigToken(FUNC2)
+ builder, graph, (gv0, gv1) = rgenop.newgraph(f2_token)
+
+ flexswitch = builder.flexswitch(gv0)
+ const21 = rgenop.genconst(21)
+
+ # case == 0
+ const0 = rgenop.genconst(0)
+ case_builder = flexswitch.add_case(const0)
+ case_args_gv = [gv1]
+ case_builder.enter_next_block([signed_tok], case_args_gv)
+ [gv1_case0] = case_args_gv
+ gv_res_case0 = case_builder.genop2('int_mul', const21, gv1_case0)
+ case_builder.finish_and_return(f2_token, gv_res_case0)
+ # default
+ default_builder = flexswitch.add_default()
+ default_args_gv = [gv1]
+ default_builder.enter_next_block([signed_tok], default_args_gv)
+ [gv1_default] = default_args_gv
+ default_builder.finish_and_return(f2_token, gv1_default)
+ # case == x
+ for x in range(1,11):
+ constx = rgenop.genconst(x)
+ case_builder = flexswitch.add_case(constx)
+ case_args_gv = [gv1]
+ case_builder.enter_next_block([signed_tok], case_args_gv)
+ [gv1_casex] = case_args_gv
+ const2px= rgenop.genconst(1<<x)
+ gv_res_casex = case_builder.genop2('int_add', const2px, gv1_casex)
+ case_builder.finish_and_return(f2_token, gv_res_casex)
+
+ gv_switch = rgenop.gencallableconst(f2_token, "large_switch", graph)
+ return gv_switch
+
+def large_switch_runner(x, y):
+ rgenop = RI386GenOp()
+ gv_switchfn = build_large_switch(rgenop)
+ switchfn = gv_switchfn.revealconst(lltype.Ptr(FUNC2))
+ res = switchfn(x, y)
+ keepalive_until_here(rgenop) # to keep the code blocks alive
+ return res
+
+def test_large_switch_direct():
+ rgenop = RI386GenOp()
+ gv_switchfn = build_large_switch(rgenop)
+ print gv_switchfn.value
+ fnptr = cast(c_void_p(gv_switchfn.value), CFUNCTYPE(c_int, c_int, c_int))
+ res = fnptr(0, 2)
+ assert res == 42
+ for x in range(1,11):
+ res = fnptr(x, 5)
+ assert res == 2**x+5
+ res = fnptr(42, 16)
+ assert res == 16
+
+def test_large_switch_compile():
+ fn = compile(large_switch_runner, [int, int])
+ res = fn(0, 2)
+ assert res == 42
+ for x in range(1,11):
+ res = fn(x, 7)
+ assert res == 2**x+7
+ res = fn(42, 18)
+ assert res == 18
More information about the Pypy-commit
mailing list