[pypy-svn] r51126 - in pypy/branch/jit-refactoring/pypy/jit/rainbow: . test
cfbolz at codespeak.net
cfbolz at codespeak.net
Wed Jan 30 14:18:01 CET 2008
Author: cfbolz
Date: Wed Jan 30 14:18:00 2008
New Revision: 51126
Added:
pypy/branch/jit-refactoring/pypy/jit/rainbow/
pypy/branch/jit-refactoring/pypy/jit/rainbow/__init__.py (contents, props changed)
pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py (contents, props changed)
pypy/branch/jit-refactoring/pypy/jit/rainbow/test/
pypy/branch/jit-refactoring/pypy/jit/rainbow/test/__init__.py (contents, props changed)
pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py (contents, props changed)
Log:
start serializing graphs for the rainbow interpreter. all very sketchy at the
moment.
Added: pypy/branch/jit-refactoring/pypy/jit/rainbow/__init__.py
==============================================================================
Added: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py
==============================================================================
--- (empty file)
+++ pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py Wed Jan 30 14:18:00 2008
@@ -0,0 +1,303 @@
+from pypy.objspace.flow import model as flowmodel
+from pypy.rpython.lltypesystem import lltype
+from pypy.jit.hintannotator.model import originalconcretetype
+from pypy.jit.timeshifter import rtimeshift, rvalue
+from pypy.rlib.unroll import unrolling_iterable
+
+class JitCode(object):
+ """
+ normal operations have the following format:
+ 2 byte - operation
+ n * 2 byte - arguments
+
+ for nonvoid results the result is appended to the varlist
+
+ red vars are just indexes
+ green vars are positive indexes
+ green consts are negative indexes
+ """
+
+ def __init__(self, code, constants):
+ self.code = code
+ self.constants = constants
+
+ def _freeze_(self):
+ return True
+
+class JitInterpreter(object):
+ def __init__(self):
+ self.opcode_implementations = []
+ self.opcode_descs = []
+ self.opname_to_index = {}
+ self.jitstate = None
+ self.bytecode = None
+ self._add_implemented_opcodes()
+
+ # construction-time interface
+
+ def _add_implemented_opcodes(self):
+ for name in dir(self):
+ if not name.startswith("opimpl_"):
+ continue
+ opname = name[len("opimpl_"):]
+ self.opname_to_index[opname] = len(self.opcode_implementations)
+ self.opcode_implementations.append(getattr(self, name).im_func)
+ self.opcode_descs.append(None)
+
+
+ def find_opcode(self, name):
+ return self.opname_to_index.get(name, -1)
+
+ def make_opcode_implementation(self, color, opdesc):
+ numargs = unrolling_iterable(range(opdesc.nb_args))
+ if color == "green":
+ def implementation(self):
+ args = ()
+ for i in numargs:
+ args.append(self.get_greenarg())
+ result = opdesc.llop(*args)
+ self.green_result(result)
+ elif color == "red":
+ if opdesc.nb_args == 1:
+ impl = rtimeshift.ll_gen1
+ elif opdesc.nb_args == 2:
+ impl = rtimeshift.ll_gen2
+ else:
+ XXX
+ def implementation(self):
+ args = (self.jitstate, )
+ for i in numargs:
+ args.append(self.get_redarg())
+ result = impl(*args)
+ self.red_result(result)
+ else:
+ assert 0, "unknown color"
+ implementation.func_name = "opimpl_%s_%s" % (color, opdesc.opname)
+ opname = "%s_%s" % (color, opdesc.opname)
+ index = self.opname_to_index[opname] = len(self.opcode_implementations)
+ self.opcode_implementations.append(implementation)
+ self.opcode_descs.append(opdesc)
+ return index
+
+
+ # operation implemetations
+ def opimpl_make_redbox(self):
+ XXX
+
+ def opimpl_goto(self):
+ XXX
+
+ def opimpl_goto_green_iftrue(self):
+ XXX
+
+ def opimpl_goto_red_iftrue(self):
+ XXX
+
+ def opimpl_red_return(self):
+ XXX
+
+ def opimpl_green_return(self):
+ XXX
+
+ def opimpl_make_new_redvars(self):
+ # an opcode with a variable number of args
+ # num_args arg_old_1 arg_new_1 ...
+ XXX
+
+ def opimpl_make_new_greenvars(self):
+ # an opcode with a variable number of args
+ # num_args arg_old_1 arg_new_1 ...
+ XXX
+
+
+class BytecodeWriter(object):
+ def __init__(self, t, hintannotator, RGenOp):
+ self.translator = t
+ self.annotator = t.annotator
+ self.hannotator = hintannotator
+ self.interpreter = JitInterpreter()
+ self.RGenOp = RGenOp
+
+ def make_bytecode(self, graph):
+ self.seen_blocks = {}
+ self.bytecode = []
+ self.constants = []
+ self.const_positions = {}
+ self.block_positions = {}
+ self.graph = graph
+ self.entrymap = flowmodel.mkentrymap(graph)
+ self.make_bytecode_block(graph.startblock)
+ self.patch_jumps()
+ return JitCode("".join(self.bytecode), self.constants)
+
+ def make_bytecode_block(self, block, insert_goto=False):
+ if block in self.block_positions:
+ if insert_goto:
+ self.emit_2byte(self.interpreter.find_opcode("goto"))
+ self.emit_4byte(self.block_positions[block])
+ return
+ # inserting a goto not necessary, falling through
+ self.current_block = block
+ self.redvar_positions = {}
+ self.greenvar_positions = {}
+ self.block_positions[block] = len(self.bytecode)
+ reds, greens = self.sort_by_color(block.inputargs)
+ # asign positions to the arguments
+ for arg in reds:
+ self.redvar_position(arg)
+ for arg in greens:
+ self.greenvar_positions(arg)
+ #self.insert_merges(block)
+ for op in block.operations:
+ self.serialize_op(op)
+ #self.insert_splits(block)
+ self.insert_exits(block)
+
+ def insert_exits(self, block):
+ if block.exits == ():
+ returnvar, = block.inputargs
+ if self.hannotator.binding(returnvar).is_green():
+ color = "green"
+ else:
+ color = "red"
+ self.emit_2byte(self.interpreter.find_opcode("%s_return" % color))
+ self.emit_2byte(self.serialize_oparg(color, returnvar))
+ elif len(block.exits) == 1:
+ link, = block.exits
+ self.insert_renaming(link.args)
+ self.make_bytecode_block(link.target, insert_goto=True)
+ else:
+ XXX
+
+ def patch_jumps(self):
+ for i in range(len(self.bytecode)):
+ if isinstance(self.bytecode[i], str):
+ continue
+ assert 0
+ # must be a block
+ index = self.block_positions[self.bytecode[i]]
+ self.bytecode[i + 0] = chr((index >> 24) & 0xff)
+ self.bytecode[i + 1] = chr((index >> 16) & 0xff)
+ self.bytecode[i + 2] = chr((index >> 8) & 0xff)
+ self.bytecode[i + 3] = chr(index & 0xff)
+
+
+ def insert_renaming(self, args):
+ reds, greens = self.sort_by_color(args)
+ for color, args in [("red", reds), ("green", greens)]:
+ result = []
+ for v in args:
+ result.append(self.serialize_oparg(color, v))
+ self.emit_2byte(self.interpreter.find_opcode(
+ "make_new_%svars" % (color, )))
+ self.emit_2byte(len(args))
+ for index in result:
+ self.emit_2byte(index)
+
+ def serialize_op(self, op):
+ color = self.opcolor(op)
+ args = []
+ for arg in op.args:
+ args.append(self.serialize_oparg(color, arg))
+ self.serialize_opcode(color, op)
+ for index in args:
+ self.emit_2byte(index)
+ if self.hannotator.binding(op.result).is_green():
+ self.green_position(op.result)
+ else:
+ self.redvar_position(op.result)
+
+
+ def serialize_opcode(self, color, op):
+ opname = op.opname
+ name = "%s_%s" % (color, opname)
+ index = self.interpreter.find_opcode(name)
+ if index == -1:
+ hop = PseudoHOP(
+ op, [self.hannotator.binding(arg) for arg in op.args],
+ self.hannotator.binding(op.result), self.RGenOp)
+ opdesc = rtimeshift.make_opdesc(hop)
+ index = self.interpreter.make_opcode_implementation(color, opdesc)
+ self.emit_2byte(index)
+
+ def serialize_oparg(self, color, arg):
+ if color == "red":
+ if self.hannotator.binding(arg).is_green():
+ return self.convert_to_red(arg)
+ return self.redvar_position(arg)
+ XXX
+
+ def convert_to_red(self, arg):
+ if arg in self.redvar_positions:
+ # already converted
+ return self.redvar_positions[arg]
+ self.emit_2byte(self.interpreter.find_opcode("make_redbox"))
+ resultindex = self.redvar_positions[arg] = len(self.redvar_positions)
+ argindex = self.green_position(arg)
+ self.emit_2byte(resultindex)
+ self.emit_2byte(argindex)
+ return resultindex
+
+ def opcolor(self, op):
+ for v in op.args:
+ if not self.hannotator.binding(v).is_green():
+ return "red"
+ if not self.hannotator.binding(op.result).is_green():
+ return "red"
+ return "green"
+
+ def redvar_position(self, arg):
+ return self.redvar_positions.setdefault(
+ arg, len(self.redvar_positions))
+
+ def green_position(self, arg):
+ if isinstance(arg, flowmodel.Variable):
+ return self.greenvar_positions.setdefault(
+ arg, len(self.greenvar_positions))
+ return -self.const_positions(arg)
+
+ def const_position(self, const):
+ if const in self.const_position:
+ return self.const_position[const]
+ XXX
+
+ def emit_2byte(self, index):
+ assert not index & 0xffff0000
+ self.bytecode.append(chr((index >> 8) & 0xff))
+ self.bytecode.append(chr(index & 0xff))
+
+ def emit_4byte(self, index):
+ self.bytecode.append(chr((index >> 24) & 0xff))
+ self.bytecode.append(chr((index >> 16) & 0xff))
+ self.bytecode.append(chr((index >> 8) & 0xff))
+ self.bytecode.append(chr(index & 0xff))
+
+ def emit_jumptarget(self, block):
+ self.bytecode.extend((block, None, None, None))
+
+ def sort_by_color(self, vars, by_color_of_vars=None):
+ reds = []
+ greens = []
+ if by_color_of_vars is None:
+ by_color_of_vars = vars
+ for v, bcv in zip(vars, by_color_of_vars):
+ if v.concretetype is lltype.Void:
+ continue
+ if self.hannotator.binding(bcv).is_green():
+ greens.append(v)
+ else:
+ reds.append(v)
+ return reds, greens
+
+# XXX too lazy to fix the interface of make_opdesc
+class PseudoHOP(object):
+ def __init__(self, op, args_s, s_result, RGenOp):
+ self.spaceop = op
+ self.args_s = args_s
+ self.s_result = s_result
+ self.rtyper = PseudoHRTyper(RGenOp)
+
+class PseudoHRTyper(object):
+ def __init__(self, RGenOp):
+ self.RGenOp = RGenOp
+
Added: pypy/branch/jit-refactoring/pypy/jit/rainbow/test/__init__.py
==============================================================================
Added: pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py
==============================================================================
--- (empty file)
+++ pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_serializegraph.py Wed Jan 30 14:18:00 2008
@@ -0,0 +1,85 @@
+from pypy.translator.translator import TranslationContext, graphof
+from pypy.jit.hintannotator.annotator import HintAnnotator
+from pypy.jit.hintannotator.policy import StopAtXPolicy, HintAnnotatorPolicy
+from pypy.jit.hintannotator.model import SomeLLAbstractConstant, OriginFlags
+from pypy.jit.rainbow.bytecode import BytecodeWriter
+from pypy.jit.codegen.llgraph.rgenop import RGenOp
+from pypy import conftest
+
+
+P_DEFAULT = HintAnnotatorPolicy(entrypoint_returns_red=False)
+P_OOPSPEC = HintAnnotatorPolicy(oopspec=True,
+ entrypoint_returns_red=False)
+P_OOPSPEC_NOVIRTUAL = HintAnnotatorPolicy(oopspec=True,
+ novirtualcontainer=True,
+ entrypoint_returns_red=False)
+P_NOVIRTUAL = HintAnnotatorPolicy(novirtualcontainer=True,
+ entrypoint_returns_red=False)
+
+class AbstractSerializationTest:
+ type_system = None
+
+ def serialize(self, func, argtypes, policy=P_DEFAULT, inline=None,
+ backendoptimize=False):
+ # build the normal ll graphs for ll_function
+ t = TranslationContext()
+ a = t.buildannotator()
+ a.build_types(func, argtypes)
+ rtyper = t.buildrtyper(type_system = self.type_system)
+ rtyper.specialize()
+ if inline:
+ auto_inlining(t, threshold=inline)
+ if backendoptimize:
+ from pypy.translator.backendopt.all import backend_optimizations
+ backend_optimizations(t)
+ graph1 = graphof(t, func)
+
+ # build hint annotator types
+ policy = self.fixpolicy(policy)
+ hannotator = HintAnnotator(base_translator=t, policy=policy)
+ hs = hannotator.build_types(graph1, [SomeLLAbstractConstant(v.concretetype,
+ {OriginFlags(): True})
+ for v in graph1.getargs()])
+ hannotator.simplify()
+ t = hannotator.translator
+ if conftest.option.view:
+ t.view()
+ graph2 = graphof(t, func)
+ writer = BytecodeWriter(t, hannotator, RGenOp)
+ jitcode = writer.make_bytecode(graph2)
+ return writer, jitcode
+
+ def fixpolicy(self, policy):
+ return policy
+
+ def test_simple(self):
+ def f(x, y):
+ return x + y
+ writer, jitcode = self.serialize(f, [int, int])
+ assert jitcode.code == code(writer.interpreter,
+ "red_int_add", 0, 1,
+ "make_new_redvars", 1, 2,
+ "make_new_greenvars", 0,
+ "red_return", 0)
+
+
+
+
+def code(interpreter, *args):
+ result = []
+ def emit_2byte(index):
+ result.append(chr((index >> 8) & 0xff))
+ result.append(chr(index & 0xff))
+ for arg in args:
+ if isinstance(arg, str):
+ emit_2byte(interpreter.find_opcode(arg))
+ elif isinstance(arg, int):
+ emit_2byte(arg)
+ else:
+ XXX
+ return "".join(result)
+
+
+
+class TestLLType(AbstractSerializationTest):
+ type_system = "lltype"
More information about the Pypy-commit
mailing list