[pypy-svn] r52577 - in pypy/branch/jit-hotpath/pypy/jit/rainbow: . test
arigo at codespeak.net
arigo at codespeak.net
Sun Mar 16 12:00:26 CET 2008
Author: arigo
Date: Sun Mar 16 12:00:24 2008
New Revision: 52577
Modified:
pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py
pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py
pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py
pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_interpreter.py
Log:
Indirect calls.
Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py (original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py Sun Mar 16 12:00:24 2008
@@ -578,6 +578,7 @@
def register_redvar(self, arg, where=-1, verbose=True):
assert arg not in self.redvar_positions
+ assert getattr(arg, 'concretetype', '?') is not lltype.Void
if where == -1:
where = self.free_red[self.current_block]
self.free_red[self.current_block] += 1
@@ -591,6 +592,7 @@
def register_greenvar(self, arg, where=None, check=True, verbose=True):
assert isinstance(arg, flowmodel.Variable) or not check
+ assert getattr(arg, 'concretetype', '?') is not lltype.Void
if where is None:
where = self.free_green[self.current_block]
self.free_green[self.current_block] += 1
@@ -825,11 +827,15 @@
return handler(op, arg, result)
def handle_concrete_hint(self, op, arg, result):
+ if arg.concretetype is lltype.Void:
+ return
assert self.hannotator.binding(arg).is_green()
assert self.hannotator.binding(result).is_green()
self.register_greenvar(result, self.green_position(arg))
def handle_variable_hint(self, op, arg, result):
+ if arg.concretetype is lltype.Void:
+ return
assert not self.hannotator.binding(result).is_green()
if self.hannotator.binding(arg).is_green():
resultindex = self.convert_to_red(arg)
@@ -838,12 +844,16 @@
self.register_redvar(result, self.redvar_position(arg))
def handle_deepfreeze_hint(self, op, arg, result):
+ if arg.concretetype is lltype.Void:
+ return
if self.varcolor(result) == "red":
self.register_redvar(result, self.redvar_position(arg))
else:
self.register_greenvar(result, self.green_position(arg))
def handle_promote_hint(self, op, arg, result):
+ if arg.concretetype is lltype.Void:
+ return
if self.varcolor(arg) == "green":
self.register_greenvar(result, self.green_position(arg))
return
@@ -912,6 +922,37 @@
has_result = (self.varcolor(op.result) != "gray" and
op.result.concretetype != lltype.Void)
+ if self.hannotator.policy.hotpath:
+ if not targets:
+ self.handle_residual_call(op, withexc)
+ return
+ if not has_result:
+ kind = "gray"
+ # for now, let's try to promote all indirect calls
+ self.emit("hp_promote")
+ self.emit(fnptrindex)
+ self.emit(self.promotiondesc_position(op.args[0].concretetype))
+ greenfnptrindex = self.register_greenvar(("promoted fnptr", op),
+ check=False)
+ args = targets.values()[0].getargs()
+ emitted_args = self.args_of_call(op.args[1:-1], args)
+ self.emit("hp_%s_indirect_call" % (kind,))
+ self.emit(*emitted_args)
+ setdescindex = self.indirectcalldesc_position(targets)
+ self.emit(greenfnptrindex, setdescindex)
+ if has_result:
+ assert self.varcolor(op.result) == "red"
+ if kind != "red":
+ assert kind == "yellow"
+ tmpindex = self.register_greenvar(("tmpresult", op),
+ check=False)
+ self.emit("make_redbox")
+ self.emit(tmpindex)
+ self.emit(self.type_position(op.result.concretetype))
+ self.register_redvar(op.result)
+ return
+
+ # ---------- non-hotpath logic follows ----------
emitted_args = []
for v in op.args[1:-1]:
if v.concretetype == lltype.Void:
@@ -1019,8 +1060,8 @@
func = self.serialize_oparg("red", fnptr)
emitted_args = []
for v in op.args[1:]:
- if v.concretetype == lltype.Void:
- continue
+ if v.concretetype == lltype.Void: # for indirect_call, this also
+ continue # skips the last argument
emitted_args.append(self.serialize_oparg("red", v))
if self.hannotator.policy.hotpath:
self.emit("hp_residual_call")
Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py (original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py Sun Mar 16 12:00:24 2008
@@ -85,10 +85,13 @@
Xxx("capture_exception")
def run_directly(self, greenargs, redargs, targetbytecode):
- calldesc = targetbytecode.owncalldesc
+ return self.perform_call_mixed(greenargs, redargs,
+ targetbytecode.gv_ownfnptr,
+ targetbytecode.owncalldesc)
+
+ def perform_call_mixed(self, greenargs, redargs, gv_func, calldesc):
try:
- gv_res = calldesc.perform_call_mixed(self.rgenop,
- targetbytecode.gv_ownfnptr,
+ gv_res = calldesc.perform_call_mixed(self.rgenop, gv_func,
greenargs, redargs)
except Exception, e:
self.capture_exception(e)
@@ -304,11 +307,6 @@
gv_res = calldesc.perform_call(self.rgenop, gv_fnptr, greenargs)
self.green_result(gv_res)
- @arguments("green_varargs", "red_varargs", "red", "indirectcalldesc")
- def opimpl_indirect_call_const(self, greenargs, redargs,
- gv_funcptr, callset):
- Xxx("indirect_call_const")
-
@arguments("oopspec", "bool", returns="red")
def opimpl_red_oopspec_call_0(self, oopspec, deepfrozen):
return self.oopspec_call(oopspec, [])
@@ -441,7 +439,10 @@
@arguments("red", "green", "green", returns="green")
def opimpl_is_constant(self, arg, true, false):
- Xxx("is_constant")
+ # we could return either true or false here, but 'false' is probably
+ # better because there is no point in fallback-interpreting the clever
+ # logic that typically follows the 'true' case.
+ return false
# hotpath-specific operations
@@ -479,6 +480,26 @@
gv_res = self.run_directly(greenargs, redargs, targetbytecode)
self.green_result(gv_res)
+ @arguments("green_varargs", "red_varargs", "green", "indirectcalldesc")
+ def opimpl_hp_red_indirect_call(self, greenargs, redargs, gv_funcptr,
+ callset):
+ gv_res = self.perform_call_mixed(greenargs, redargs, gv_funcptr,
+ callset.calldesc)
+ self.red_result(gv_res)
+
+ @arguments("green_varargs", "red_varargs", "green", "indirectcalldesc")
+ def opimpl_hp_gray_indirect_call(self, greenargs, redargs, gv_funcptr,
+ callset):
+ self.perform_call_mixed(greenargs, redargs, gv_funcptr,
+ callset.calldesc)
+
+ @arguments("green_varargs", "red_varargs", "green", "indirectcalldesc")
+ def opimpl_hp_yellow_indirect_call(self, greenargs, redargs, gv_funcptr,
+ callset):
+ gv_res = self.perform_call_mixed(greenargs, redargs, gv_funcptr,
+ callset.calldesc)
+ self.green_result(gv_res)
+
@arguments("red", "calldesc", "bool", "bool", "red_varargs")
def opimpl_hp_residual_call(self, gv_func, calldesc, withexc, has_result,
redargs_gv):
Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py (original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py Sun Mar 16 12:00:24 2008
@@ -896,8 +896,7 @@
promotebox, promotiondesc)
assert False, "unreachable"
- @arguments("green_varargs", "red_varargs", "bytecode")
- def opimpl_hp_red_direct_call(self, greenargs, redargs, targetbytecode):
+ def hp_direct_call(self, greenargs, redargs, targetbytecode):
frame = rtimeshift.VirtualFrame(self.frame, None)
self.frame = self.jitstate.frame = frame
frame.pc = 0
@@ -905,9 +904,23 @@
frame.local_boxes = redargs
frame.local_green = greenargs
+ @arguments("green_varargs", "red_varargs", "bytecode")
+ def opimpl_hp_red_direct_call(self, greenargs, redargs, targetbytecode):
+ self.hp_direct_call(greenargs, redargs, targetbytecode)
+
opimpl_hp_gray_direct_call = opimpl_hp_red_direct_call
opimpl_hp_yellow_direct_call = opimpl_hp_red_direct_call
+ @arguments("green_varargs", "red_varargs", "green", "indirectcalldesc")
+ def opimpl_hp_red_indirect_call(self, greenargs, redargs, gv_funcptr,
+ callset):
+ addr = gv_funcptr.revealconst(llmemory.Address)
+ bytecode = callset.bytecode_for_address(addr)
+ self.hp_direct_call(greenargs, redargs, bytecode)
+
+ opimpl_hp_gray_indirect_call = opimpl_hp_red_indirect_call
+ opimpl_hp_yellow_indirect_call = opimpl_hp_red_indirect_call
+
@arguments("red", "calldesc", "bool", "bool", "red_varargs")
def opimpl_hp_residual_call(self, funcbox, calldesc, withexc, has_result,
redargs):
Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_interpreter.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_interpreter.py (original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_interpreter.py Sun Mar 16 12:00:24 2008
@@ -12,6 +12,7 @@
#
# i = 1024
# while i > 0:
+# i >>= 1
# ...real test code here...
# MyJitDriver.jit_merge_point(...)
# MyJitDriver.can_enter_jit(...)
@@ -879,10 +880,14 @@
res = self.interpret(f, [4, 212], [])
assert res == 212
- def test_simple_meth(self):
+ def test_simple_yellow_meth(self):
+ class MyJitDriver(JitDriver):
+ greens = []
+ reds = ['flag', 'res', 'i']
+
class Base(object):
def m(self):
- raise NotImplementedError
+ return 21
pass # for inspect.getsource() bugs
class Concrete(Base):
@@ -891,43 +896,61 @@
pass # for inspect.getsource() bugs
def f(flag):
- if flag:
- o = Base()
- else:
- o = Concrete()
- return o.m()
-
- res = self.interpret(f, [0], [0])
- assert res == 42
- self.check_insns({})
+ i = 1024
+ while i > 0:
+ i >>= 1
+ if flag:
+ o = Base()
+ else:
+ o = Concrete()
+ res = o.m() # yellow call
+ MyJitDriver.jit_merge_point(flag=flag, res=res, i=i)
+ MyJitDriver.can_enter_jit(flag=flag, res=res, i=i)
+ return res
- res = self.interpret(f, [0], [])
+ res = self.run(f, [0], threshold=2)
assert res == 42
- self.check_insns(indirect_call=0)
+ self.check_insns_in_loops({'int_is_true': 1,
+ 'int_gt': 1, 'int_rshift': 1})
def test_simple_red_meth(self):
+ class MyJitDriver(JitDriver):
+ greens = []
+ reds = ['flag', 'res', 'i']
+
class Base(object):
- def m(self, n):
- raise NotImplementedError
+ def m(self, i):
+ return 21 + i
pass # for inspect.getsource() bugs
class Concrete(Base):
- def m(self, n):
- return 21*n
+ def m(self, i):
+ return 42 - i
pass # for inspect.getsource() bugs
- def f(flag, x):
- if flag:
- o = Base()
- else:
- o = Concrete()
- return o.m(x)
+ def f(flag):
+ i = 1024
+ while i > 0:
+ i >>= 1
+ if flag:
+ o = Base()
+ else:
+ o = Concrete()
+ res = o.m(i) # red call
+ MyJitDriver.jit_merge_point(flag=flag, res=res, i=i)
+ MyJitDriver.can_enter_jit(flag=flag, res=res, i=i)
+ return res
- res = self.interpret(f, [0, 2], [0])
+ res = self.run(f, [0], threshold=2)
assert res == 42
- self.check_insns({'int_mul': 1})
+ self.check_insns_in_loops({'int_is_true': 1, 'int_sub': 1,
+ 'int_gt': 1, 'int_rshift': 1})
def test_simple_red_meth_vars_around(self):
+ class MyJitDriver(JitDriver):
+ greens = ['y']
+ reds = ['flag', 'x', 'z', 'res', 'i']
+
class Base(object):
def m(self, n):
raise NotImplementedError
@@ -939,27 +962,48 @@
pass # for inspect.getsource() bugs
def f(flag, x, y, z):
- if flag:
- o = Base()
- else:
- o = Concrete()
- return (o.m(x)+y)-z
+ i = 1024
+ while i > 0:
+ i >>= 1
+ if flag:
+ o = Base()
+ else:
+ o = Concrete()
+ hint(y, concrete=True)
+ res = (o.m(x)+y)-z
+ MyJitDriver.jit_merge_point(flag=flag, res=res, i=i,
+ x=x, y=y, z=z)
+ MyJitDriver.can_enter_jit(flag=flag, res=res, i=i,
+ x=x, y=y, z=z)
+ return res
- res = self.interpret(f, [0, 2, 7, 5], [0])
+ res = self.run(f, [0, 2, 7, 5], threshold=2)
assert res == 44
- self.check_insns({'int_mul': 1, 'int_add': 1, 'int_sub': 1})
+ self.check_insns_in_loops({'int_is_true': 1,
+ 'int_mul': 1, 'int_add': 1, 'int_sub': 1,
+ 'int_gt': 1, 'int_rshift': 1})
def test_green_red_mismatch_in_call(self):
+ class MyJitDriver(JitDriver):
+ greens = ['x', 'y']
+ reds = ['u', 'res', 'i']
+
def add(a,b, u):
return a+b
def f(x, y, u):
- r = add(x+1,y+1, u)
- z = x+y
- z = hint(z, concrete=True) + r # this checks that 'r' is green
- return hint(z, variable=True)
+ i = 1024
+ while i > 0:
+ i >>= 1
+ r = add(x+1,y+1, u)
+ z = x+y
+ z = hint(z, concrete=True) + r # this checks that 'r' is green
+ res = hint(z, variable=True)
+ MyJitDriver.jit_merge_point(x=x, y=y, u=u, res=res, i=i)
+ MyJitDriver.can_enter_jit(x=x, y=y, u=u, res=res, i=i)
+ return res
- res = self.interpret(f, [4, 5, 0], [])
+ res = self.run(f, [4, 5, 0], threshold=2)
assert res == 20
@@ -976,6 +1020,10 @@
assert res == 120
def test_simple_indirect_call(self):
+ class MyJitDriver(JitDriver):
+ greens = ['flag']
+ reds = ['v', 'res', 'i']
+
def g1(v):
return v * 2
@@ -983,17 +1031,28 @@
return v + 2
def f(flag, v):
- if hint(flag, concrete=True):
- g = g1
- else:
- g = g2
- return g(v)
+ i = 1024
+ while i > 0:
+ i >>= 1
+ if hint(flag, concrete=True):
+ g = g1
+ else:
+ g = g2
+ res = g(v)
+ MyJitDriver.jit_merge_point(flag=flag, v=v, res=res, i=i)
+ MyJitDriver.can_enter_jit(flag=flag, v=v, res=res, i=i)
+ return res
- res = self.interpret(f, [0, 40], [0])
+ res = self.run(f, [0, 40], threshold=2)
assert res == 42
- self.check_insns({'int_add': 1})
+ self.check_insns_in_loops({'int_add': 1,
+ 'int_gt': 1, 'int_rshift': 1})
def test_normalize_indirect_call(self):
+ class MyJitDriver(JitDriver):
+ greens = ['flag']
+ reds = ['v', 'res', 'i']
+
def g1(v):
return -17
@@ -1001,21 +1060,32 @@
return v + 2
def f(flag, v):
- if hint(flag, concrete=True):
- g = g1
- else:
- g = g2
- return g(v)
+ i = 1024
+ while i > 0:
+ i >>= 1
+ if hint(flag, concrete=True):
+ g = g1
+ else:
+ g = g2
+ res = g(v)
+ MyJitDriver.jit_merge_point(flag=flag, v=v, res=res, i=i)
+ MyJitDriver.can_enter_jit(flag=flag, v=v, res=res, i=i)
+ return res
- res = self.interpret(f, [0, 40], [0])
+ res = self.run(f, [0, 40], threshold=2)
assert res == 42
- self.check_insns({'int_add': 1})
+ self.check_insns_in_loops({'int_add': 1,
+ 'int_gt': 1, 'int_rshift': 1})
- res = self.interpret(f, [1, 40], [0])
+ res = self.run(f, [1, 40], threshold=2)
assert res == -17
- self.check_insns({})
+ self.check_insns_in_loops({'int_gt': 1, 'int_rshift': 1})
def test_normalize_indirect_call_more(self):
+ class MyJitDriver(JitDriver):
+ greens = ['flag']
+ reds = ['v', 'res', 'i']
+
def g1(v):
if v >= 0:
return -17
@@ -1026,28 +1096,38 @@
return v + 2
def f(flag, v):
- w = g1(v)
- if hint(flag, concrete=True):
- g = g1
- else:
- g = g2
- return g(v) + w
+ i = 1024
+ while i > 0:
+ i >>= 1
+ w = g1(v)
+ if hint(flag, concrete=True):
+ g = g1
+ else:
+ g = g2
+ res = g(v) + w
+ MyJitDriver.jit_merge_point(flag=flag, v=v, res=res, i=i)
+ MyJitDriver.can_enter_jit(flag=flag, v=v, res=res, i=i)
+ return res
- res = self.interpret(f, [0, 40], [0])
+ res = self.run(f, [0, 40], threshold=2)
assert res == 25
- self.check_insns({'int_add': 2, 'int_ge': 1})
+ self.check_insns_in_loops({'int_add': 2, 'int_ge': 1,
+ 'int_gt': 1, 'int_rshift': 1})
- res = self.interpret(f, [1, 40], [0])
+ res = self.run(f, [1, 40], threshold=2)
assert res == -34
- self.check_insns({'int_ge': 2, 'int_add': 1})
+ self.check_insns_in_loops({'int_ge': 2,
+ 'int_gt': 1, 'int_rshift': 1})
- res = self.interpret(f, [0, -1000], [0])
+ res = self.run(f, [0, -1000], threshold=2)
assert res == f(False, -1000)
- self.check_insns({'int_add': 2, 'int_ge': 1})
+ self.check_insns_in_loops({'int_add': 2, 'int_ge': 1,
+ 'int_gt': 1, 'int_rshift': 1})
- res = self.interpret(f, [1, -1000], [0])
+ res = self.run(f, [1, -1000], threshold=2)
assert res == f(True, -1000)
- self.check_insns({'int_ge': 2, 'int_add': 1})
+ self.check_insns_in_loops({'int_ge': 2,
+ 'int_gt': 1, 'int_rshift': 1})
def test_green_char_at_merge(self):
def f(c, x):
More information about the Pypy-commit
mailing list