[pypy-svn] r51174 - in pypy/branch/jit-refactoring/pypy/jit: rainbow rainbow/test timeshifter

cfbolz at codespeak.net cfbolz at codespeak.net
Fri Feb 1 13:47:42 CET 2008


Author: cfbolz
Date: Fri Feb  1 13:47:40 2008
New Revision: 51174

Added:
   pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_interpreter.py   (contents, props changed)
Modified:
   pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py
   pypy/branch/jit-refactoring/pypy/jit/timeshifter/rtimeshift.py
Log:
the first test where the rainbow interpreter actually runs passes. required a
very messy test runner and some whacking.


Modified: pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py	(original)
+++ pypy/branch/jit-refactoring/pypy/jit/rainbow/bytecode.py	Fri Feb  1 13:47:40 2008
@@ -1,3 +1,4 @@
+from pypy.rlib.rarithmetic import intmask
 from pypy.objspace.flow import model as flowmodel
 from pypy.rpython.lltypesystem import lltype
 from pypy.jit.hintannotator.model import originalconcretetype
@@ -24,15 +25,40 @@
     def _freeze_(self):
         return True
 
+SIGN_EXTEND2 = 1 << 15
+
+STOP = object()
+
 class JitInterpreter(object):
     def __init__(self):
         self.opcode_implementations = []
         self.opcode_descs = []
         self.opname_to_index = {}
         self.jitstate = None
+        self.queue = None
         self.bytecode = None
+        self.pc = -1
         self._add_implemented_opcodes()
 
+    def run(self, jitstate, bytecode, greenargs, redargs):
+        self.jitstate = jitstate
+        self.queue = rtimeshift.ensure_queue(jitstate,
+                                             rtimeshift.BaseDispatchQueue)
+        rtimeshift.enter_frame(self.jitstate, self.queue)
+        self.frame = self.jitstate.frame
+        self.frame.pc = 0
+        self.frame.bytecode = bytecode
+        self.frame.local_boxes = redargs
+        self.frame.local_green = greenargs
+        self.bytecode_loop()
+
+    def bytecode_loop(self):
+        while 1:
+            bytecode = self.load_2byte()
+            result = self.opcode_implementations[bytecode](self)
+            if result is STOP:
+                return
+
     # construction-time interface
 
     def _add_implemented_opcodes(self):
@@ -44,7 +70,6 @@
             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)
 
@@ -54,7 +79,9 @@
             def implementation(self):
                 args = ()
                 for i in numargs:
-                    args.append(self.get_greenarg())
+                    genconst = self.get_greenarg()
+                    arg = self.jitstate.curbuilder.revealconst(opdesc.ARGS[i])
+                    args += (arg, )
                 result = opdesc.llop(*args)
                 self.green_result(result)
         elif color == "red":
@@ -65,12 +92,9 @@
             else:
                 XXX
             def implementation(self):
-                XXX
-                # the following is nonsense: the green arguments are
-                # GenConsts, so there are revealconsts missing
-                args = (self.jitstate, )
+                args = (opdesc, self.jitstate, )
                 for i in numargs:
-                    args.append(self.get_redarg())
+                    args += (self.get_redarg(), )
                 result = impl(*args)
                 self.red_result(result)
         else:
@@ -83,12 +107,46 @@
         return index
             
 
-    # operation implemetations
+    # operation helper functions
+
+    def load_2byte(self):
+        pc = self.frame.pc
+        result = ((ord(self.frame.bytecode.code[pc]) << 8) |
+                   ord(self.frame.bytecode.code[pc + 1]))
+        self.frame.pc = pc + 2
+        return intmask((result ^ SIGN_EXTEND2) - SIGN_EXTEND2)
+
+    def load_4byte(self):
+        pc = self.frame.pc
+        result = ((ord(self.frame.bytecode.code[pc + 0]) << 24) |
+                  (ord(self.frame.bytecode.code[pc + 1]) << 16) |
+                  (ord(self.frame.bytecode.code[pc + 2]) <<  8) |
+                  (ord(self.frame.bytecode.code[pc + 3]) <<  0))
+        self.frame.pc = pc + 4
+        return intmask(result)
+
+    def get_greenarg(self):
+        i = self.load_2byte()
+        if i < 0:
+            return self.frame.bytecode.constants[~i]
+        return self.frame.local_green[i]
+
+    def get_redarg(self):
+        return self.frame.local_boxes[self.load_2byte()]
+
+    def red_result(self, box):
+        self.frame.local_boxes.append(box)
+
+    def green_result(self, gv):
+        self.frame.local_green.append(gv)
+
+    # operation implementations
     def opimpl_make_redbox(self):
         XXX
 
     def opimpl_goto(self):
-        XXX
+        target = self.load_4byte()
+        self.frame.pc = target
 
     def opimpl_green_goto_iftrue(self):
         XXX
@@ -97,20 +155,35 @@
         XXX
 
     def opimpl_red_return(self):
-        XXX
+        rtimeshift.save_return(self.jitstate)
+        # XXX for now
+        newstate = rtimeshift.leave_graph_red(self.queue, is_portal=True)
+        self.jitstate = newstate
+        return STOP
 
     def opimpl_green_return(self):
         XXX
+        return STOP # XXX wrong, of course
 
     def opimpl_make_new_redvars(self):
         # an opcode with a variable number of args
         # num_args arg_old_1 arg_new_1 ...
-        XXX
+        num = self.load_2byte()
+        newlocalboxes = []
+        for i in range(num):
+            newlocalboxes.append(self.get_redarg())
+        self.frame.local_boxes = newlocalboxes
 
     def opimpl_make_new_greenvars(self):
         # an opcode with a variable number of args
         # num_args arg_old_1 arg_new_1 ...
-        XXX
+        num = self.load_2byte()
+        newgreens = []
+        for i in range(num):
+            newgreens.append(self.get_greenarg())
+        self.frame.local_green = newgreens
+
+
 
 
 class BytecodeWriter(object):
@@ -268,7 +341,6 @@
         return color
         
     def register_redvar(self, arg):
-        print "register_redvar", arg
         assert arg not in self.redvar_positions
         self.redvar_positions[arg] = result = self.free_red[self.current_block]
         self.free_red[self.current_block] += 1
@@ -288,7 +360,7 @@
     def green_position(self, arg):
         if isinstance(arg, flowmodel.Variable):
             return self.greenvar_positions[arg]
-        return -self.const_position(arg) - 1
+        return ~self.const_position(arg)
 
     def const_position(self, const):
         if const in self.const_positions:
@@ -374,15 +446,15 @@
 
 
 
-# XXX too lazy to fix the interface of make_opdesc
+# XXX too lazy to fix the interface of make_opdesc, ExceptionDesc
 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)
+        self.rtyper = PseudoHRTyper(RGenOp=RGenOp)
 
 class PseudoHRTyper(object):
-    def __init__(self, RGenOp):
-        self.RGenOp = RGenOp
+    def __init__(self, **args):
+        self.__dict__.update(**args)
 

Added: pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_interpreter.py
==============================================================================
--- (empty file)
+++ pypy/branch/jit-refactoring/pypy/jit/rainbow/test/test_interpreter.py	Fri Feb  1 13:47:40 2008
@@ -0,0 +1,140 @@
+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.hintannotator.model import originalconcretetype
+from pypy.jit.rainbow.bytecode import BytecodeWriter, label, tlabel, assemble
+from pypy.jit.codegen.llgraph.rgenop import RGenOp
+from pypy.jit.rainbow.test.test_serializegraph import AbstractSerializationTest
+from pypy.jit.rainbow import bytecode
+from pypy.jit.timeshifter import rtimeshift, exception, rvalue
+from pypy.rpython.lltypesystem import lltype, rstr
+from pypy.rpython.llinterp import LLInterpreter
+from pypy.annotation import model as annmodel
+from pypy import conftest
+
+def getargtypes(annotator, values):
+    return [annotation(annotator, x) for x in values]
+
+def annotation(a, x):
+    T = lltype.typeOf(x)
+    if T == lltype.Ptr(rstr.STR):
+        t = str
+    else:
+        t = annmodel.lltype_to_annotation(T)
+    return a.typeannotation(t)
+
+P_OOPSPEC_NOVIRTUAL = HintAnnotatorPolicy(oopspec=True,
+                                          novirtualcontainer=True,
+                                          entrypoint_returns_red=False)
+
+class AbstractInterpretationTest(object):
+
+    def serialize(self, func, values, backendoptimize=False):
+        # build the normal ll graphs for ll_function
+        t = TranslationContext()
+        a = t.buildannotator()
+        argtypes = getargtypes(a, values)
+        a.build_types(func, argtypes)
+        rtyper = t.buildrtyper(type_system = self.type_system)
+        rtyper.specialize()
+        self.rtyper = rtyper
+        if backendoptimize:
+            from pypy.translator.backendopt.all import backend_optimizations
+            backend_optimizations(t)
+        graph1 = graphof(t, func)
+
+        # build hint annotator types
+        hannotator = HintAnnotator(base_translator=t, policy=P_OOPSPEC_NOVIRTUAL)
+        hs = hannotator.build_types(graph1, [SomeLLAbstractConstant(v.concretetype,
+                                                                    {OriginFlags(): True})
+                                             for v in graph1.getargs()])
+        hannotator.simplify()
+        t = hannotator.translator
+        self.hannotator = hannotator
+        if conftest.option.view:
+            t.view()
+        graph2 = graphof(t, func)
+        self.graph = graph2
+        writer = BytecodeWriter(t, hannotator, RGenOp)
+        jitcode = writer.make_bytecode(graph2)
+        argcolors = []
+        for i, ll_val in enumerate(values):
+            color = writer.varcolor(graph2.startblock.inputargs[i])
+            argcolors.append(color)
+        return writer, jitcode, argcolors
+
+    def interpret(self, ll_function, values, opt_consts=[], *args, **kwds):
+        # XXX clean this mess up
+        writer, jitcode, argcolors = self.serialize(ll_function, values)
+        hrtyper = bytecode.PseudoHRTyper(RGenOp=writer.RGenOp,
+                                         annotator=writer.translator.annotator,
+                                         rtyper=writer.translator.annotator.base_translator.rtyper)
+        edesc = exception.ExceptionDesc(hrtyper, False)
+        rgenop = writer.RGenOp()
+        # make residual functype
+        FUNC = lltype.FuncType([lltype.Signed], lltype.Signed)
+        ha = self.hannotator
+        RESTYPE = originalconcretetype(self.hannotator.binding(self.graph.getreturnvar()))
+        ARGS = []
+        for var in self.graph.getargs():
+            # XXX ignoring virtualizables for now
+            ARGS.append(originalconcretetype(self.hannotator.binding(var)))
+        FUNC = lltype.FuncType(ARGS, RESTYPE)
+        sigtoken = rgenop.sigToken(FUNC)
+        builder, gv_generated, inputargs_gv = rgenop.newgraph(sigtoken, "generated")
+        print builder, builder.rgenop, rgenop
+        builder.start_writing()
+        jitstate = rtimeshift.JITState(builder, None,
+                                       edesc.null_exc_type_box,
+                                       edesc.null_exc_value_box)
+        def ll_finish_jitstate(jitstate, exceptiondesc, graphsigtoken):
+            returnbox = rtimeshift.getreturnbox(jitstate)
+            gv_ret = returnbox.getgenvar(jitstate)
+            builder = jitstate.curbuilder
+            for virtualizable_box in jitstate.virtualizables:
+                assert isinstance(virtualizable_box, rvalue.PtrRedBox)
+                content = virtualizable_box.content
+                assert isinstance(content, rcontainer.VirtualizableStruct)
+                content.store_back(jitstate)        
+            exceptiondesc.store_global_excdata(jitstate)
+            jitstate.curbuilder.finish_and_return(graphsigtoken, gv_ret)
+        # build arguments
+        greenargs = []
+        redargs = []
+        residualargs = []
+        i = 0
+        for color, ll_val in zip(argcolors, values):
+            if color == "green":
+                greenargs.append(writer.RGenOp.constPrebuiltGlobal(const.value))
+            else:
+                TYPE = lltype.typeOf(ll_val)
+                kind = rgenop.kindToken(TYPE)
+                boxcls = rvalue.ll_redboxcls(TYPE)
+                redargs.append(boxcls(kind, inputargs_gv[i]))
+                residualargs.append(ll_val)
+                i += 1
+        writer.interpreter.run(jitstate, jitcode, greenargs, redargs)
+        ll_finish_jitstate(writer.interpreter.jitstate, edesc, sigtoken)
+        builder.end()
+        generated = gv_generated.revealconst(lltype.Ptr(FUNC))
+        graph = generated._obj.graph
+        if conftest.option.view:
+            graph.show()
+        llinterp = LLInterpreter(self.rtyper)
+        res = llinterp.eval_graph(graph, residualargs)
+        return res
+
+    def Xtest_return_green(self):
+        def f():
+            return 1
+        self.interpret(f, [])
+
+    def test_very_simple(self):
+        def f(x, y):
+            return x + y
+        res = self.interpret(f, [1, 2])
+        assert res == 3
+
+class TestLLType(AbstractInterpretationTest):
+    type_system = "lltype"

Modified: pypy/branch/jit-refactoring/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/branch/jit-refactoring/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/branch/jit-refactoring/pypy/jit/timeshifter/rtimeshift.py	Fri Feb  1 13:47:40 2008
@@ -78,7 +78,7 @@
 def ll_gen1(opdesc, jitstate, argbox):
     ARG0 = opdesc.ARG0
     RESULT = opdesc.RESULT
-    opname = opdesc.name
+    opname = opdesc.opname
     if opdesc.tryfold and argbox.is_constant():
         arg = rvalue.ll_getvalue(argbox, ARG0)
         if not opdesc.canraise:
@@ -106,7 +106,7 @@
     ARG0 = opdesc.ARG0
     ARG1 = opdesc.ARG1
     RESULT = opdesc.RESULT
-    opname = opdesc.name
+    opname = opdesc.opname
     if opdesc.tryfold and argbox0.is_constant() and argbox1.is_constant():
         # const propagate
         arg0 = rvalue.ll_getvalue(argbox0, ARG0)
@@ -991,6 +991,7 @@
         self.backframe = backframe
         self.dispatchqueue = dispatchqueue
         #self.local_boxes = ... set by callers
+        #self.local_green = ... set by callers
 
     def enter_block(self, incoming, memo):
         for box in self.local_boxes:



More information about the Pypy-commit mailing list