[pypy-commit] pypy virtual-arguments: backout 21b2273ebbc5

fijal noreply at buildbot.pypy.org
Fri Jul 20 10:47:53 CEST 2012


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: virtual-arguments
Changeset: r56249:f82061c0426c
Date: 2012-07-20 10:38 +0200
http://bitbucket.org/pypy/pypy/changeset/f82061c0426c/

Log:	backout 21b2273ebbc5

diff --git a/pypy/jit/tl/spli/__init__.py b/pypy/jit/tl/spli/__init__.py
new file mode 100644
diff --git a/pypy/jit/tl/spli/autopath.py b/pypy/jit/tl/spli/autopath.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/tl/spli/autopath.py
@@ -0,0 +1,131 @@
+"""
+self cloning, automatic path configuration 
+
+copy this into any subdirectory of pypy from which scripts need 
+to be run, typically all of the test subdirs. 
+The idea is that any such script simply issues
+
+    import autopath
+
+and this will make sure that the parent directory containing "pypy"
+is in sys.path. 
+
+If you modify the master "autopath.py" version (in pypy/tool/autopath.py) 
+you can directly run it which will copy itself on all autopath.py files
+it finds under the pypy root directory. 
+
+This module always provides these attributes:
+
+    pypydir    pypy root directory path 
+    this_dir   directory where this autopath.py resides 
+
+"""
+
+def __dirinfo(part):
+    """ return (partdir, this_dir) and insert parent of partdir
+    into sys.path.  If the parent directories don't have the part
+    an EnvironmentError is raised."""
+
+    import sys, os
+    try:
+        head = this_dir = os.path.realpath(os.path.dirname(__file__))
+    except NameError:
+        head = this_dir = os.path.realpath(os.path.dirname(sys.argv[0]))
+
+    error = None
+    while head:
+        partdir = head
+        head, tail = os.path.split(head)
+        if tail == part:
+            checkfile = os.path.join(partdir, os.pardir, 'pypy', '__init__.py')
+            if not os.path.exists(checkfile):
+                error = "Cannot find %r" % (os.path.normpath(checkfile),)
+            break
+    else:
+        error = "Cannot find the parent directory %r of the path %r" % (
+            partdir, this_dir)
+    if not error:
+        # check for bogus end-of-line style (e.g. files checked out on
+        # Windows and moved to Unix)
+        f = open(__file__.replace('.pyc', '.py'), 'r')
+        data = f.read()
+        f.close()
+        if data.endswith('\r\n') or data.endswith('\r'):
+            error = ("Bad end-of-line style in the .py files. Typically "
+                     "caused by a zip file or a checkout done on Windows and "
+                     "moved to Unix or vice-versa.")
+    if error:
+        raise EnvironmentError("Invalid source tree - bogus checkout! " +
+                               error)
+    
+    pypy_root = os.path.join(head, '')
+    try:
+        sys.path.remove(head)
+    except ValueError:
+        pass
+    sys.path.insert(0, head)
+
+    munged = {}
+    for name, mod in sys.modules.items():
+        if '.' in name:
+            continue
+        fn = getattr(mod, '__file__', None)
+        if not isinstance(fn, str):
+            continue
+        newname = os.path.splitext(os.path.basename(fn))[0]
+        if not newname.startswith(part + '.'):
+            continue
+        path = os.path.join(os.path.dirname(os.path.realpath(fn)), '')
+        if path.startswith(pypy_root) and newname != part:
+            modpaths = os.path.normpath(path[len(pypy_root):]).split(os.sep)
+            if newname != '__init__':
+                modpaths.append(newname)
+            modpath = '.'.join(modpaths)
+            if modpath not in sys.modules:
+                munged[modpath] = mod
+
+    for name, mod in munged.iteritems():
+        if name not in sys.modules:
+            sys.modules[name] = mod
+        if '.' in name:
+            prename = name[:name.rfind('.')]
+            postname = name[len(prename)+1:]
+            if prename not in sys.modules:
+                __import__(prename)
+                if not hasattr(sys.modules[prename], postname):
+                    setattr(sys.modules[prename], postname, mod)
+
+    return partdir, this_dir
+
+def __clone():
+    """ clone master version of autopath.py into all subdirs """
+    from os.path import join, walk
+    if not this_dir.endswith(join('pypy','tool')):
+        raise EnvironmentError("can only clone master version "
+                               "'%s'" % join(pypydir, 'tool',_myname))
+
+
+    def sync_walker(arg, dirname, fnames):
+        if _myname in fnames:
+            fn = join(dirname, _myname)
+            f = open(fn, 'rwb+')
+            try:
+                if f.read() == arg:
+                    print "checkok", fn
+                else:
+                    print "syncing", fn
+                    f = open(fn, 'w')
+                    f.write(arg)
+            finally:
+                f.close()
+    s = open(join(pypydir, 'tool', _myname), 'rb').read()
+    walk(pypydir, sync_walker, s)
+
+_myname = 'autopath.py'
+
+# set guaranteed attributes
+
+pypydir, this_dir = __dirinfo('pypy')
+
+if __name__ == '__main__':
+    __clone()
diff --git a/pypy/jit/tl/spli/examples.py b/pypy/jit/tl/spli/examples.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/tl/spli/examples.py
@@ -0,0 +1,16 @@
+
+def f():
+    return 1
+
+print f()
+
+def adder(a, b):
+    return a + b
+
+def while_loop():
+    i = 0
+    while i < 10000000:
+        i = i + 1
+    return None
+
+while_loop()
diff --git a/pypy/jit/tl/spli/execution.py b/pypy/jit/tl/spli/execution.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/tl/spli/execution.py
@@ -0,0 +1,47 @@
+from pypy.jit.tl.spli import interpreter, objects, pycode
+
+
+def run_from_cpython_code(co, args=[], locs=None, globs=None):
+    space = objects.DumbObjSpace()
+    pyco = pycode.Code._from_code(space, co)
+    return run(pyco, [space.wrap(arg) for arg in args], locs, globs)
+
+def run(pyco, args, locs=None, globs=None):
+    frame = interpreter.SPLIFrame(pyco, locs, globs)
+    frame.set_args(args)
+    return get_ec().execute_frame(frame)
+
+
+def get_ec():
+    ec = state.get()
+    if ec is None:
+        ec = ExecutionContext()
+        state.set(ec)
+    return ec
+
+
+class State(object):
+
+    def __init__(self):
+        self.value = None
+
+    def get(self):
+        return self.value
+
+    def set(self, new):
+        self.value = new
+
+state = State()
+
+
+class ExecutionContext(object):
+
+    def __init__(self):
+        self.framestack = []
+
+    def execute_frame(self, frame):
+        self.framestack.append(frame)
+        try:
+            return frame.run()
+        finally:
+            self.framestack.pop()
diff --git a/pypy/jit/tl/spli/interpreter.py b/pypy/jit/tl/spli/interpreter.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/tl/spli/interpreter.py
@@ -0,0 +1,241 @@
+import os
+from pypy.tool import stdlib_opcode
+from pypy.jit.tl.spli import objects, pycode
+from pypy.rlib.unroll import unrolling_iterable
+from pypy.rlib.jit import JitDriver, promote, dont_look_inside
+from pypy.rlib.objectmodel import we_are_translated
+
+opcode_method_names = stdlib_opcode.host_bytecode_spec.method_names
+unrolling_opcode_descs = unrolling_iterable(
+    stdlib_opcode.host_bytecode_spec.ordered_opdescs)
+HAVE_ARGUMENT = stdlib_opcode.host_HAVE_ARGUMENT
+
+compare_ops = [
+    "cmp_lt",   # "<"
+    "cmp_le",   # "<="
+    "cmp_eq",   # "=="
+    "cmp_ne",   # "!="
+    "cmp_gt",   # ">"
+    "cmp_ge",   # ">="
+#    "cmp_in",
+#    "cmp_not_in",
+#    "cmp_is",
+#    "cmp_is_not",
+#    "cmp_exc_match",
+]
+unrolling_compare_dispatch_table = unrolling_iterable(
+    enumerate(compare_ops))
+
+jitdriver = JitDriver(greens = ['instr_index', 'code'],
+                      reds = ['frame'],
+                      virtualizables = ['frame'])
+
+
+class BlockUnroller(Exception):
+    pass
+
+class Return(BlockUnroller):
+
+    def __init__(self, value):
+        self.value = value
+
+class MissingOpcode(Exception):
+    pass
+
+class SPLIFrame(object):
+
+    _virtualizable2_ = ['value_stack[*]', 'locals[*]', 'stack_depth']
+
+    @dont_look_inside
+    def __init__(self, code, locs=None, globs=None):
+        self.code = code
+        self.value_stack = [None] * code.co_stacksize
+        self.locals = [None] * code.co_nlocals
+        if locs is not None:
+            self.locals_dict = locs
+        else:
+            self.locals_dict = {}
+        if globs is not None:
+            self.globs = globs
+        else:
+            self.globs = {}
+        self.stack_depth = 0
+
+    def set_args(self, args):
+        for i in range(len(args)):
+            self.locals[i] = args[i]
+
+    def run(self):
+        self.stack_depth = 0
+        try:
+            self._dispatch_loop()
+        except Return, ret:
+            return ret.value
+
+    def _dispatch_loop(self):
+        code = self.code.co_code
+        instr_index = 0
+        while True:
+            jitdriver.jit_merge_point(code=code, instr_index=instr_index,
+                                      frame=self)
+            self.stack_depth = promote(self.stack_depth)
+            op = ord(code[instr_index])
+            instr_index += 1
+            if op >= HAVE_ARGUMENT:
+                low = ord(code[instr_index])
+                hi = ord(code[instr_index + 1])
+                oparg = (hi << 8) | low
+                instr_index += 2
+            else:
+                oparg = 0
+            if we_are_translated():
+                for opdesc in unrolling_opcode_descs:
+                    if op == opdesc.index:
+                        meth = getattr(self, opdesc.methodname)
+                        instr_index = meth(oparg, instr_index, code)
+                        break
+                else:
+                    raise MissingOpcode(op)
+            else:
+                meth = getattr(self, opcode_method_names[op])
+                instr_index = meth(oparg, instr_index, code)
+
+    def push(self, value):
+        self.value_stack[self.stack_depth] = value
+        self.stack_depth += 1
+
+    def pop(self):
+        sd = self.stack_depth - 1
+        assert sd >= 0
+        self.stack_depth = sd
+        val = self.value_stack[sd]
+        self.value_stack[sd] = None
+        return val
+
+    def pop_many(self, n):
+        return [self.pop() for i in range(n)]
+
+    def peek(self):
+        sd = self.stack_depth - 1
+        assert sd >= 0
+        return self.value_stack[sd]
+
+    def POP_TOP(self, _, next_instr, code):
+        self.pop()
+        return next_instr
+
+    def LOAD_FAST(self, name_index, next_instr, code):
+        assert name_index >= 0
+        self.push(self.locals[name_index])
+        return next_instr
+
+    def STORE_FAST(self, name_index, next_instr, code):
+        assert name_index >= 0
+        self.locals[name_index] = self.pop()
+        return next_instr
+
+    def LOAD_NAME(self, name_index, next_instr, code):
+        name = self.code.co_names[name_index]
+        self.push(self.locals_dict[name])
+        return next_instr
+
+    def STORE_NAME(self, name_index, next_instr, code):
+        name = self.code.co_names[name_index]
+        self.locals_dict[name] = self.pop()
+        return next_instr
+
+    def LOAD_GLOBAL(self, name_index, next_instr, code):
+        name = self.code.co_names[name_index]
+        self.push(self.globs[name])
+        return next_instr
+
+    def STORE_GLOBAL(self, name_index, next_instr, code):
+        name = self.code.co_names[name_index]
+        self.globs[name] = self.pop()
+        return next_instr
+
+    def RETURN_VALUE(self, _, next_instr, code):
+        raise Return(self.pop())
+
+    def LOAD_CONST(self, const_index, next_instr, code):
+        self.push(self.code.co_consts_w[const_index])
+        return next_instr
+
+    def BINARY_ADD(self, _, next_instr, code):
+        right = self.pop()
+        left = self.pop()
+        self.push(left.add(right))
+        return next_instr
+
+    def BINARY_SUBTRACT(self, _, next_instr, code):
+        right = self.pop()
+        left = self.pop()
+        self.push(left.sub(right))
+        return next_instr
+
+    def BINARY_AND(self, _, next_instr, code):
+        right = self.pop()
+        left = self.pop()
+        self.push(left.and_(right))
+        return next_instr        
+
+    def SETUP_LOOP(self, _, next_instr, code):
+        return next_instr
+
+    def POP_BLOCK(self, _, next_instr, code):
+        return next_instr
+
+    def JUMP_IF_FALSE(self, arg, next_instr, code):
+        w_cond = self.peek()
+        if not w_cond.is_true():
+            next_instr += arg
+        return next_instr
+
+    def POP_JUMP_IF_FALSE(self, arg, next_instr, code):
+        w_cond = self.pop()
+        if not w_cond.is_true():
+            next_instr = arg
+        return next_instr
+
+    def JUMP_FORWARD(self, arg, next_instr, code):
+        return next_instr + arg
+
+    def JUMP_ABSOLUTE(self, arg, next_instr, code):
+        jitdriver.can_enter_jit(frame=self, code=code, instr_index=arg)
+        return arg
+
+    def COMPARE_OP(self, arg, next_instr, code):
+        right = self.pop()
+        left = self.pop()
+        for num, name in unrolling_compare_dispatch_table:
+            if num == arg:
+                self.push(getattr(left, name)(right))
+        return next_instr
+
+    def MAKE_FUNCTION(self, _, next_instr, code):
+        func_code = self.pop().as_interp_class(pycode.Code)
+        func = objects.Function(func_code, self.globs)
+        self.push(func)
+        return next_instr
+
+    def CALL_FUNCTION(self, arg_count, next_instr, code):
+        args = self.pop_many(arg_count)
+        func = self.pop()
+        self.push(func.call(args))
+        return next_instr
+
+    def PRINT_ITEM(self, _, next_instr, code):
+        value = self.pop().repr().as_str()
+        os.write(1, value)
+        return next_instr
+
+    def PRINT_NEWLINE(self, _, next_instr, code):
+        os.write(1, '\n')
+        return next_instr
+
+
+items = []
+for item in unrolling_opcode_descs._items:
+    if getattr(SPLIFrame, item.methodname, None) is not None:
+        items.append(item)
+unrolling_opcode_descs = unrolling_iterable(items)
diff --git a/pypy/jit/tl/spli/objects.py b/pypy/jit/tl/spli/objects.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/tl/spli/objects.py
@@ -0,0 +1,158 @@
+from pypy.interpreter.baseobjspace import ObjSpace, Wrappable
+from pypy.rlib.objectmodel import specialize
+
+class DumbObjSpace(ObjSpace):
+    """Implement just enough of the ObjSpace API to satisfy PyCode."""
+
+    @specialize.argtype(1)
+    def wrap(self, x):
+        if isinstance(x, int):
+            return Int(x)
+        elif isinstance(x, str):
+            return Str(x)
+        elif x is None:
+            return spli_None
+        elif isinstance(x, Wrappable):
+            return x.__spacebind__(self)
+        elif isinstance(x, SPLIObject):
+            return x # Already done.
+        else:
+            raise NotImplementedError("Wrapping %s" % x)
+
+    def new_interned_str(self, x):
+        return self.wrap(x)
+
+
+class SPLIException(Exception):
+    pass
+
+
+class W_TypeError(SPLIException):
+    pass
+
+
+class SPLIObject(object):
+
+    def add(self, other):
+        raise W_TypeError
+
+    def sub(self, other):
+        raise W_TypeError    
+
+    def and_(self, other):
+        raise W_TypeError    
+
+    def call(self, args):
+        raise W_TypeError
+
+    def cmp_lt(self, other):
+        raise W_TypeError
+
+    def cmp_gt(self, other):
+        raise W_TypeError
+
+    def cmp_eq(self, other):
+        raise W_TypeError
+
+    def cmp_ne(self, other):
+        raise W_TypeError
+
+    def cmp_ge(self, other):
+        raise W_TypeError
+
+    def cmp_le(self, other):
+        raise W_TypeError
+
+    def as_int(self):
+        raise W_TypeError
+
+    def as_str(self):
+        raise W_TypeError
+
+    def repr(self):
+        return Str("<SPLI object>")
+
+    def is_true(self):
+        raise W_TypeError
+
+    def as_interp_class(self, cls):
+        if not isinstance(self, cls):
+            raise W_TypeError
+        return self
+
+
+class Bool(SPLIObject):
+
+    def __init__(self, value):
+        self.value = value
+
+    def is_true(self):
+        return self.value
+
+    def repr(self):
+        if self.is_true():
+            name = "True"
+        else:
+            name = "False"
+        return Str(name)
+
+
+class Int(SPLIObject):
+
+    def __init__(self, value):
+        self.value = value
+
+    def add(self, other):
+        return Int(self.value + other.as_int())
+
+    def sub(self, other):
+        return Int(self.value - other.as_int())
+
+    def and_(self, other):
+        return Int(self.value & other.as_int())
+
+    def cmp_lt(self, other):
+        return Bool(self.value < other.as_int())
+
+    def as_int(self):
+        return self.value
+
+    def is_true(self):
+        return bool(self.value)
+
+    def repr(self):
+        return Str(str(self.value))
+
+
+class Str(SPLIObject):
+
+    def __init__(self, value):
+        self.value = value
+
+    def as_str(self):
+        return self.value
+
+    def add(self, other):
+        return Str(self.value + other.as_str())
+
+    def repr(self):
+        return Str("'" + self.value + "'")
+
+
+class SPLINone(SPLIObject):
+
+    def repr(self):
+        return Str('None')
+
+spli_None = SPLINone()
+
+
+class Function(SPLIObject):
+
+    def __init__(self, code, globs):
+        self.code = code
+        self.globs = globs
+
+    def call(self, args):
+        from pypy.jit.tl.spli import execution
+        return execution.run(self.code, args, None, self.globs)
diff --git a/pypy/jit/tl/spli/pycode.py b/pypy/jit/tl/spli/pycode.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/tl/spli/pycode.py
@@ -0,0 +1,22 @@
+from pypy.interpreter import pycode
+from pypy.jit.tl.spli import objects
+
+
+class Code(objects.SPLIObject):
+
+    def __init__(self, argcount, nlocals, stacksize, code, consts, names):
+        """Initialize a new code object from parameters given by
+        the pypy compiler"""
+        self.co_argcount = argcount
+        self.co_nlocals = nlocals
+        self.co_stacksize = stacksize
+        self.co_code = code
+        self.co_consts_w = consts
+        self.co_names = names
+
+    @classmethod
+    def _from_code(cls, space, code, hidden_applevel=False, code_hook=None):
+        pyco = pycode.PyCode._from_code(space, code, code_hook=cls._from_code)
+        return cls(pyco.co_argcount, pyco.co_nlocals, pyco.co_stacksize,
+                   pyco.co_code, pyco.co_consts_w,
+                   [name.as_str() for name in pyco.co_names_w])
diff --git a/pypy/jit/tl/spli/serializer.py b/pypy/jit/tl/spli/serializer.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/tl/spli/serializer.py
@@ -0,0 +1,117 @@
+
+""" Usage:
+serialize.py python_file func_name output_file
+"""
+
+import autopath
+import py
+import sys
+import types
+from pypy.jit.tl.spli.objects import Int, Str, spli_None
+from pypy.jit.tl.spli.pycode import Code
+from pypy.rlib.rstruct.runpack import runpack
+import struct
+
+FMT = 'iiii'
+int_lgt = len(struct.pack('i', 0))
+header_lgt = int_lgt * len(FMT)
+
+class NotSupportedFormat(Exception):
+    pass
+
+def serialize_str(value):
+    return struct.pack('i', len(value)) + value
+
+def unserialize_str(data, start):
+    end_lgt = start + int_lgt
+    lgt = runpack('i', data[start:end_lgt])
+    assert lgt >= 0
+    end_str = end_lgt + lgt
+    return data[end_lgt:end_str], end_str
+
+def serialize_const(const):
+    if isinstance(const, int):
+        return 'd' + struct.pack('i', const)
+    elif isinstance(const, str):
+        return 's' + serialize_str(const)
+    elif const is None:
+        return 'n'
+    elif isinstance(const, types.CodeType):
+        return 'c' + serialize(const)
+    else:
+        raise NotSupportedFormat(str(const))
+
+def unserialize_const(c, start):
+    assert start >= 0
+    if c[start] == 'd':
+        end = start + int_lgt + 1
+        intval = runpack('i', c[start + 1:end])
+        return Int(intval), end
+    elif c[start] == 's':
+        value, end = unserialize_str(c, start + 1)
+        return Str(value), end
+    elif c[start] == 'n':
+        return spli_None, start + 1
+    elif c[start] == 'c':
+        return unserialize_code(c, start + 1)
+    else:
+        raise NotSupportedFormat(c[start])
+
+def unserialize_consts(constrepr):
+    pos = int_lgt
+    consts_w = []
+    num = runpack('i', constrepr[:int_lgt])
+    for i in range(num):
+        next_const, pos = unserialize_const(constrepr, pos)
+        consts_w.append(next_const)
+    return consts_w, pos
+
+def unserialize_names(namesrepr, num):
+    pos = 0
+    names = []
+    for i in range(num):
+        name, pos = unserialize_str(namesrepr, pos)
+        names.append(name)
+    return names, pos
+
+def unserialize_code(coderepr, start=0):
+    coderepr = coderepr[start:]
+    header = coderepr[:header_lgt]
+    argcount, nlocals, stacksize, code_len = runpack(FMT, header)
+    assert code_len >= 0
+    names_pos = code_len + header_lgt
+    code = coderepr[header_lgt:names_pos]
+    num = runpack('i', coderepr[names_pos:names_pos + int_lgt])
+    names, end_names = unserialize_names(coderepr[names_pos + int_lgt:], num)
+    const_start = names_pos + int_lgt + end_names
+    consts, pos = unserialize_consts(coderepr[const_start:])
+    pos = start + const_start + pos
+    return Code(argcount, nlocals, stacksize, code, consts, names), pos
+
+# ------------------- PUBLIC API ----------------------
+
+def serialize(code):
+    header = struct.pack(FMT, code.co_argcount, code.co_nlocals,
+                         code.co_stacksize, len(code.co_code))
+    namesrepr = (struct.pack('i', len(code.co_names)) +
+                 "".join(serialize_str(name) for name in code.co_names))
+    constsrepr = (struct.pack('i', len(code.co_consts)) +
+                  "".join([serialize_const(const) for const in code.co_consts]))
+    return header + code.co_code + namesrepr + constsrepr
+
+def deserialize(data, start=0):
+    return unserialize_code(data)[0]
+
+def main(argv):
+    if len(argv) != 3:
+        print __doc__
+        sys.exit(1)
+    code_file = argv[1]
+    mod = py.path.local(code_file).read()
+    r = serialize(compile(mod, code_file, "exec"))
+    outfile = py.path.local(argv[2])
+    outfile.write(r)
+
+if __name__ == '__main__':
+    import sys
+    main(sys.argv)
diff --git a/pypy/jit/tl/spli/targetspli.py b/pypy/jit/tl/spli/targetspli.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/tl/spli/targetspli.py
@@ -0,0 +1,38 @@
+
+""" usage: spli-c code_obj_file [i:int_arg s:s_arg ...]
+"""
+
+import sys, autopath, os
+from pypy.jit.tl.spli import execution, serializer, objects
+from pypy.rlib.streamio import open_file_as_stream
+
+
+def unwrap_arg(arg):
+    if arg.startswith('s:'):
+        return objects.Str(arg[2:])
+    elif arg.startswith('i:'):
+        return objects.Int(int(arg[2:]))
+    else:
+        raise NotImplementedError
+
+def entry_point(argv):
+    if len(argv) < 2:
+        print __doc__
+        os._exit(1)
+    args = argv[2:]
+    stream = open_file_as_stream(argv[1])
+    co = serializer.deserialize(stream.readall())
+    w_args = [unwrap_arg(args[i]) for i in range(len(args))]
+    execution.run(co, w_args)
+    return 0
+
+def target(drver, args):
+    return entry_point, None
+
+def jitpolicy(driver):
+    """Returns the JIT policy to use when translating."""
+    from pypy.jit.codewriter.policy import JitPolicy
+    return JitPolicy()
+
+if __name__ == '__main__':
+    entry_point(sys.argv)
diff --git a/pypy/jit/tl/spli/test/__init__.py b/pypy/jit/tl/spli/test/__init__.py
new file mode 100644
diff --git a/pypy/jit/tl/spli/test/test_interpreter.py b/pypy/jit/tl/spli/test/test_interpreter.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/tl/spli/test/test_interpreter.py
@@ -0,0 +1,113 @@
+import py
+import os
+from pypy.jit.tl.spli import execution, objects
+
+class TestSPLIInterpreter:
+
+    def eval(self, func, args=[]):
+        return execution.run_from_cpython_code(func.func_code, args)
+
+    def test_int_add(self):
+        def f():
+            return 4 + 6
+        v = self.eval(f)
+        assert isinstance(v, objects.Int)
+        assert v.value == 10
+        def f():
+            a = 4
+            return a + 6
+        assert self.eval(f).value == 10
+
+    def test_str(self):
+        def f():
+            return "Hi!"
+        v = self.eval(f)
+        assert isinstance(v, objects.Str)
+        assert v.value == "Hi!"
+        def f():
+            a = "Hello, "
+            return a + "SPLI world!"
+        v = self.eval(f)
+        assert isinstance(v, objects.Str)
+        assert v.value == "Hello, SPLI world!"
+
+    def test_comparison(self):
+        def f(i):
+            return i < 10
+
+        v = self.eval(f, [0])
+        assert isinstance(v, objects.Bool)
+        assert v.value == True
+
+    def test_while_loop(self):
+        def f():
+            i = 0
+            while i < 100:
+                i = i + 1
+            return i
+
+        v = self.eval(f)
+        assert v.value == 100
+
+    def test_invalid_adds(self):
+        def f():
+            "3" + 3
+        py.test.raises(objects.W_TypeError, self.eval, f)
+        def f():
+            3 + "3"
+        py.test.raises(objects.W_TypeError, self.eval, f)
+
+    def test_call(self):
+        code = compile("""
+def g():
+    return 4
+def f():
+    return g() + 3
+res = f()""", "<string>", "exec")
+        globs = {}
+        mod_res = execution.run_from_cpython_code(code, [], globs, globs)
+        assert mod_res is objects.spli_None
+        assert len(globs) == 3
+        assert globs["res"].as_int() == 7
+
+    def test_print(self):
+        def f(thing):
+            print thing
+        things = (
+            ("x", "'x'"),
+            (4, "4"),
+            (True, "True"),
+            (False, "False"),
+        )
+        def mock_os_write(fd, what):
+            assert fd == 1
+            buf.append(what)
+        save = os.write
+        os.write = mock_os_write
+        try:
+            for obj, res in things:
+                buf = []
+                assert self.eval(f, [obj]) is objects.spli_None
+                assert "".join(buf) == res + '\n'
+        finally:
+            os.write = save
+
+    def test_binary_op(self):
+        def f(a, b):
+            return a & b - a
+
+        v = self.eval(f, [1, 2])
+        assert v.value == f(1, 2)
+
+    def test_while_2(self):
+        def f(a, b):
+            total = 0
+            i = 0
+            while i < 100:
+                if i & 1:
+                    total = total + a
+                else:
+                    total = total + b
+                i = i + 1
+            return total
+        assert self.eval(f, [1, 10]).value == f(1, 10)
diff --git a/pypy/jit/tl/spli/test/test_jit.py b/pypy/jit/tl/spli/test/test_jit.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/tl/spli/test/test_jit.py
@@ -0,0 +1,74 @@
+
+import py
+from pypy.jit.metainterp.test.support import JitMixin
+from pypy.jit.tl.spli import interpreter, objects, serializer
+from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
+from pypy.jit.backend.llgraph import runner
+from pypy.rpython.annlowlevel import llstr, hlstr
+
+class TestSPLIJit(JitMixin):
+    type_system = 'lltype'
+    CPUClass = runner.LLtypeCPU
+    
+    def interpret(self, f, args):
+        coderepr = serializer.serialize(f.func_code)
+        arg_params = ", ".join(['arg%d' % i for i in range(len(args))])
+        arg_ass = ";".join(['frame.locals[%d] = space.wrap(arg%d)' % (i, i) for
+                                 i in range(len(args))])
+        space = objects.DumbObjSpace()
+        source = py.code.Source("""
+        def bootstrap(%(arg_params)s):
+            co = serializer.deserialize(coderepr)
+            frame = interpreter.SPLIFrame(co)
+            %(arg_ass)s
+            return frame.run()
+        """ % locals())
+        d = globals().copy()
+        d['coderepr'] = coderepr
+        d['space'] = space
+        exec source.compile() in d
+        return self.meta_interp(d['bootstrap'], args, listops=True)
+    
+    def test_basic(self):
+        def f():
+            i = 0
+            while i < 20:
+                i = i + 1
+            return i
+        self.interpret(f, [])
+        self.check_resops(new_with_vtable=0)
+
+    def test_bridge(self):
+        py.test.skip('We currently cant virtualize across bridges')
+        def f(a, b):
+            total = 0
+            i = 0
+            while i < 100:
+                if i & 1:
+                    total = total + a
+                else:
+                    total = total + b
+                i = i + 1
+            return total
+
+        self.interpret(f, [1, 10])
+        self.check_resops(new_with_vtable=0)
+
+    def test_bridge_bad_case(self):
+        py.test.skip('We currently cant virtualize across bridges')
+        def f(a, b):
+            i = 0
+            while i < 100:
+                if i & 1:
+                    a = a + 1
+                else:
+                    b = b + 1
+                i = i + 1
+            return a + b
+
+        self.interpret(f, [1, 10])
+        self.check_resops(new_with_vtable=1) # XXX should eventually be 0?
+        # I think it should be either 0 or 2, 1 makes little sense
+        # If the loop after entering goes first time to the bridge, a
+        # is rewrapped again, without preserving the identity. I'm not
+        # sure how bad it is
diff --git a/pypy/jit/tl/spli/test/test_serializer.py b/pypy/jit/tl/spli/test/test_serializer.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/tl/spli/test/test_serializer.py
@@ -0,0 +1,30 @@
+from pypy.jit.tl.spli.serializer import serialize, deserialize
+from pypy.jit.tl.spli import execution, pycode, objects
+
+class TestSerializer(object):
+
+    def eval(self, code, args=[]):
+        return execution.run(code, args)
+
+    def test_basic(self):
+        def f():
+            return 1
+
+        coderepr = serialize(f.func_code)
+        code = deserialize(coderepr)
+        assert code.co_nlocals == f.func_code.co_nlocals
+        assert code.co_argcount == 0
+        assert code.co_stacksize == f.func_code.co_stacksize
+        assert code.co_names == []
+        assert self.eval(code).value == 1
+
+    def test_nested_code_objects(self):
+        mod = """
+def f(): return 1
+f()"""
+        data = serialize(compile(mod, "spli", "exec"))
+        spli_code = deserialize(data)
+        assert len(spli_code.co_consts_w) == 2
+        assert isinstance(spli_code.co_consts_w[0], pycode.Code)
+        assert spli_code.co_consts_w[0].co_consts_w[0] is objects.spli_None
+        assert spli_code.co_consts_w[0].co_consts_w[1].as_int() == 1
diff --git a/pypy/jit/tl/spli/test/test_translated.py b/pypy/jit/tl/spli/test/test_translated.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/tl/spli/test/test_translated.py
@@ -0,0 +1,24 @@
+
+from pypy.rpython.test.test_llinterp import interpret
+from pypy.jit.tl.spli import execution, objects
+from pypy.jit.tl.spli.serializer import serialize, deserialize
+
+class TestSPLITranslated(object):
+
+    def test_one(self):
+        def f(a, b):
+            return a + b
+        data = serialize(f.func_code)
+        space = objects.DumbObjSpace()
+        def run(a, b):
+            co = deserialize(data)
+            args = []
+            args.append(space.wrap(a))
+            args.append(space.wrap(b))
+            w_res = execution.run(co, args)
+            assert isinstance(w_res, objects.Int)
+            return w_res.value
+
+        assert run(2, 3) == 5
+        res = interpret(run, [2, 3])
+        assert res == 5


More information about the pypy-commit mailing list