[pypy-svn] r41309 - pypy/dist/pypy/jit/tl

arigo at codespeak.net arigo at codespeak.net
Mon Mar 26 10:33:20 CEST 2007


Author: arigo
Date: Mon Mar 26 10:33:19 2007
New Revision: 41309

Added:
   pypy/dist/pypy/jit/tl/targettiny2.py   (contents, props changed)
   pypy/dist/pypy/jit/tl/tiny2.py   (contents, props changed)
Log:
A "tiny" interpreter, sadly heavily hacked at to be JIT-friendly.


Added: pypy/dist/pypy/jit/tl/targettiny2.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/jit/tl/targettiny2.py	Mon Mar 26 10:33:19 2007
@@ -0,0 +1,28 @@
+from pypy.jit.tl import tiny2
+from pypy.jit.codegen.hlinfo import highleveljitinfo
+
+
+def entry_point(args):
+    highleveljitinfo.sys_executable = args[0]
+    bytecode = [s for s in args[1].split(' ') if s != '']
+    args = [tiny2.StrBox(arg) for arg in args[2:]]
+    res = tiny2.interpret(bytecode, args)
+    print res.as_str()
+    return 0
+
+def target(driver, args):
+    return entry_point, None
+
+# ____________________________________________________________
+
+from pypy.jit.hintannotator.annotator import HintAnnotatorPolicy
+
+class MyHintAnnotatorPolicy(HintAnnotatorPolicy):
+    novirtualcontainer = True
+    oopspec = True
+
+    def look_inside_graph(self, graph):
+        return getattr(graph, 'func', None) is not tiny2.myint_internal
+
+def portal(driver):
+    return tiny2.interpret, MyHintAnnotatorPolicy()

Added: pypy/dist/pypy/jit/tl/tiny2.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/jit/tl/tiny2.py	Mon Mar 26 10:33:19 2007
@@ -0,0 +1,131 @@
+from pypy.rlib.objectmodel import hint, _is_early_constant
+import sys
+
+
+INVALID = -sys.maxint-1
+
+def myint_internal(s, start=0):
+    if start >= len(s):
+        return INVALID
+    res = 0
+    while start < len(s):
+        c = s[start]
+        n = ord(c) - ord('0')
+        if not (0 <= n <= 9):
+            return INVALID
+        res = res * 10 + n
+        start += 1
+    return res
+
+def myint(s, start=0):
+    if _is_early_constant(s):
+        s = hint(s, promote=True)
+        start = hint(start, promote=True)
+        n = myint_internal(s, start)
+        if n == INVALID:
+            raise ValueError
+    else:
+        n = myint_internal(s, start)
+        if n == INVALID:
+            raise ValueError
+    return n
+
+
+class Box:
+    pass
+
+class IntBox(Box):
+    def __init__(self, intval):
+        self.intval = intval
+    def as_int(self):
+        return self.intval
+    def as_str(self):
+        return str(self.intval)
+
+class StrBox(Box):
+    def __init__(self, strval):
+        self.strval = strval
+    def as_int(self):
+        return myint(self.strval)
+    def as_str(self):
+        return self.strval
+
+
+def func_add_int(ix, iy): return ix + iy
+def func_sub_int(ix, iy): return ix - iy
+def func_mul_int(ix, iy): return ix * iy
+
+def func_add_str(sx, sy): return sx + ' ' + sy
+def func_sub_str(sx, sy): return sx + '-' + sy
+def func_mul_str(sx, sy): return sx + '*' + sy
+
+def op2(stack, func_int, func_str):
+    y = stack.pop()
+    hint(y.__class__, promote=True)
+    x = stack.pop()
+    hint(x.__class__, promote=True)
+    try:
+        z = IntBox(func_int(x.as_int(), y.as_int()))
+    except ValueError:
+        z = StrBox(func_str(x.as_str(), y.as_str()))
+    stack.append(z)
+
+
+def interpret(bytecode, args):
+    hint(None, global_merge_point=True)
+    bytecode = hint(bytecode, deepfreeze=True)
+    # ------------------------------
+    oldargs = args
+    argcount = hint(len(oldargs), promote=True)
+    args = []
+    n = 0
+    while n < argcount:
+        hint(n, concrete=True)
+        args.append(oldargs[n])
+        n += 1
+    # ------------------------------
+    loops = []
+    stack = []
+    pos = 0
+    while pos < len(bytecode):
+        hint(None, global_merge_point=True)
+        opcode = bytecode[pos]
+        hint(opcode, concrete=True)
+        pos += 1
+        if   opcode == 'ADD': op2(stack, func_add_int, func_add_str)
+        elif opcode == 'SUB': op2(stack, func_sub_int, func_sub_str)
+        elif opcode == 'MUL': op2(stack, func_mul_int, func_mul_str)
+        elif opcode[0] == '#':
+            n = myint(opcode, start=1)
+            stack.append(args[n-1])
+        elif opcode.startswith('->#'):
+            n = myint(opcode, start=3)
+            args[n-1] = stack.pop()
+        elif opcode == '{':
+            loops.append(pos)
+        elif opcode == '}':
+            if stack.pop().as_int() == 0:
+                loops.pop()
+            else:
+                pos = loops[-1]
+                pos = hint(pos, promote=True)
+        else:
+            stack.append(StrBox(opcode))
+    while len(stack) > 1:
+        op2(stack, func_add_int, func_add_str)
+    return stack.pop()
+
+
+def test_main():
+    main = """#1 5 ADD""".split()
+    res = interpret(main, [IntBox(20)])
+    assert res.as_int() == 25
+    res = interpret(main, [StrBox('foo')])
+    assert res.as_str() == 'foo 5'
+
+FACTORIAL = """The factorial of #1 is
+                  1 { #1 MUL #1 1 SUB ->#1 #1 }""".split()
+
+def test_factorial():
+    res = interpret(FACTORIAL, [IntBox(5)])
+    assert res.as_str() == 'The factorial of 5 is 120'



More information about the Pypy-commit mailing list