[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