[pypy-svn] r20848 - in pypy/dist/pypy/jit: . test

ericvrp at codespeak.net ericvrp at codespeak.net
Wed Dec 7 17:23:01 CET 2005


Author: ericvrp
Date: Wed Dec  7 17:23:00 2005
New Revision: 20848

Modified:
   pypy/dist/pypy/jit/bytecode.py
   pypy/dist/pypy/jit/test/test_tl.py
   pypy/dist/pypy/jit/tl.py
Log:
(arre, ericvrp)
Added lots more tests and basic bytecodes, including comparisons,
conditional branches, function calls, returns, exits.


Modified: pypy/dist/pypy/jit/bytecode.py
==============================================================================
--- pypy/dist/pypy/jit/bytecode.py	(original)
+++ pypy/dist/pypy/jit/bytecode.py	Wed Dec  7 17:23:00 2005
@@ -1,4 +1,34 @@
-PUSH    = 'P'
-POP     = 'p'
-ADD     = '+'
-INVALID = '!'
+opcode = 0
+def next_opcode():
+    global opcode
+    opcode += 1
+    return opcode
+
+PUSH    = next_opcode()   #1 operand
+POP     = next_opcode()
+SWAP    = next_opcode()
+ROT     = next_opcode()
+
+PICK    = next_opcode()   #1 operand (DUP = PICK,0)
+PUT     = next_opcode()   #1 operand
+
+ADD     = next_opcode()
+SUB     = next_opcode()
+MUL     = next_opcode()
+DIV     = next_opcode()
+
+EQ      = next_opcode()
+NE      = next_opcode()
+LT      = next_opcode()
+LE      = next_opcode()
+GT      = next_opcode()
+GE      = next_opcode()
+
+BR_COND = next_opcode()  #1 operand offset
+
+CALL    = next_opcode()  #1 operand offset
+RETURN  = next_opcode()
+
+EXIT    = next_opcode()
+
+INVALID = next_opcode()

Modified: pypy/dist/pypy/jit/test/test_tl.py
==============================================================================
--- pypy/dist/pypy/jit/test/test_tl.py	(original)
+++ pypy/dist/pypy/jit/test/test_tl.py	Wed Dec  7 17:23:00 2005
@@ -1,4 +1,5 @@
 import py
+import operator
 from pypy.jit.tl import interp
 from pypy.jit.bytecode import *
 
@@ -24,30 +25,108 @@
     builder.import_module()
     return builder.get_entry_point()  
 
+def compile(insn):
+    return ''.join([chr(i & 0xff) for i in insn])
+
 # actual tests go here
 
 def test_tl_push():
-    assert interp(PUSH+chr(16)) == 16
+    assert interp(compile([PUSH, 16])) == 16
 
 def test_tl_pop():
-    assert interp( ''.join([PUSH,chr(16), PUSH,chr(42), PUSH,chr(200), POP]) ) == 42
+    assert interp( compile([PUSH,16, PUSH,42, PUSH,100, POP]) ) == 42
 
 def test_tl_add():
-    assert interp( ''.join([PUSH,chr(42), PUSH,chr(200), ADD]) ) == 242
-    assert interp( ''.join([PUSH,chr(16), PUSH,chr(42), PUSH,chr(200), ADD]) ) == 242
+    assert interp( compile([PUSH,42, PUSH,100, ADD]) ) == 142
+    assert interp( compile([PUSH,16, PUSH,42, PUSH,100, ADD]) ) == 142
 
 def test_tl_error():
-    py.test.raises(IndexError, interp,POP)
-    py.test.raises(IndexError, interp,ADD)
-    py.test.raises(IndexError, interp,''.join([PUSH,chr(200), ADD]) )
+    py.test.raises(IndexError, interp,compile([POP]))
+    py.test.raises(IndexError, interp,compile([ADD]))
+    py.test.raises(IndexError, interp,compile([PUSH,100, ADD]) )
 
 def test_tl_invalid_codetype():
     py.test.raises(TypeError, interp,[INVALID])
 
 def test_tl_invalid_bytecode():
-    py.test.raises(RuntimeError, interp,INVALID)
+    py.test.raises(RuntimeError, interp,compile([INVALID]))
 
 def test_tl_translatable():
-    code = ''.join([PUSH,chr(42), PUSH,chr(200), ADD])
+    code = compile([PUSH,42, PUSH,100, ADD])
     fn = translate(interp, [str])
     assert interp(code) == fn(code)
+
+def test_swap():
+    code = [PUSH,42, PUSH, 84]
+    assert interp(compile(code)) == 84
+    code.append(SWAP)
+    assert interp(compile(code)) == 42
+    code.append(POP)
+    assert interp(compile(code)) == 84
+
+def test_pick():
+    values = [7, 8, 9]
+    code = []
+    for v in reversed(values):
+        code.extend([PUSH, v])
+
+    for i, v in enumerate(values):
+        assert interp(compile(code + [PICK,i])) == v
+
+def test_put():
+    values = [1,2,7,-3]
+    code = [PUSH,0] * len(values)
+    for i, v in enumerate(values):
+        code += [PUSH,v, PUT,i]
+
+    for i, v in enumerate(values):
+        assert interp(compile(code + [PICK,i])) == v
+
+ops = [ (ADD, operator.add, ((2, 4), (1, 1), (-1, 1))),
+        (SUB, operator.sub, ((2, 4), (4, 2), (1, 1))),
+        (MUL, operator.mul, ((2, 4), (4, 2), (1, 1), (-1, 6), (0, 5))),
+        (DIV, operator.div, ((2, 4), (4, 2), (1, 1), (-4, -2), (0, 9), (9, -3))),
+        (EQ, operator.eq, ((0, 0), (0, 1), (1, 0), (1, 1), (-1, 0), (0, -1), (-1, -1), (1, -1),  (-1, 1))),
+        (NE, operator.ne, ((0, 0), (0, 1), (1, 0), (1, 1), (-1, 0), (0, -1), (-1, -1), (1, -1),  (-1, 1))),
+        (LT, operator.lt, ((0, 0), (0, 1), (1, 0), (1, 1), (-1, 0), (0, -1), (-1, -1), (1, -1),  (-1, 1))),
+        (LE, operator.le, ((0, 0), (0, 1), (1, 0), (1, 1), (-1, 0), (0, -1), (-1, -1), (1, -1),  (-1, 1))),
+        (GT, operator.gt, ((0, 0), (0, 1), (1, 0), (1, 1), (-1, 0), (0, -1), (-1, -1), (1, -1),  (-1, 1))),
+        (GE, operator.ge, ((0, 0), (0, 1), (1, 0), (1, 1), (-1, 0), (0, -1), (-1, -1), (1, -1),  (-1, 1))),
+      ]
+
+def test_ops():
+      for insn, pyop, values in ops:
+          for first, second in values:
+              code = [PUSH, first, PUSH, second, insn]
+              assert interp(compile(code)) == pyop(first, second)
+
+
+def test_branch_forward():
+    assert interp(compile([PUSH,1, PUSH,0, BR_COND,2, PUSH,-1])) == -1
+    assert interp(compile([PUSH,1, PUSH,1, BR_COND,2, PUSH,-1])) == 1
+    assert interp(compile([PUSH,1, PUSH,-1, BR_COND,2, PUSH,-1])) == 1
+
+def test_branch_backwards():
+    assert interp(compile([PUSH,0, PUSH,1, BR_COND,6, PUSH,-1, PUSH,3, BR_COND,4, PUSH,2, BR_COND,-10])) == -1
+
+def test_branch0():
+    assert interp(compile([PUSH,7, PUSH,1, BR_COND,0])) == 7
+
+def test_exit():
+    assert py.test.raises(IndexError, interp, compile([EXIT]))
+    assert interp(compile([PUSH,7, EXIT, PUSH,5])) == 7
+
+def test_rot():
+    code = [PUSH,1, PUSH,2, PUSH,3, ROT,3] 
+    assert interp(compile(code)) == 2
+    assert interp(compile(code + [POP])) == 1
+    assert interp(compile(code + [POP, POP])) == 3
+
+    py.test.raises(IndexError, interp, compile([PUSH,1, PUSH,2, PUSH,3, ROT,4]))
+
+def test_call_ret():
+    assert py.test.raises(IndexError, interp, compile([RETURN]))
+    assert interp(compile([PUSH,6, RETURN, PUSH,4, EXIT, PUSH,9])) == 9
+    assert interp(compile([CALL,0])) == 2
+
+    assert interp(compile([PUSH,1, CALL,5, PUSH,2, CALL,2, EXIT, RETURN, ROT,3, ADD, SWAP, RETURN])) == 3

Modified: pypy/dist/pypy/jit/tl.py
==============================================================================
--- pypy/dist/pypy/jit/tl.py	(original)
+++ pypy/dist/pypy/jit/tl.py	Wed Dec  7 17:23:00 2005
@@ -3,6 +3,12 @@
 import py
 from bytecode import *
 
+def char2int(c):
+    t = ord(c)
+    if t & 128:
+        t = -(-ord(c) & 0xff)
+    return t
+
 def interp(code=''):
     if not isinstance(code,str):
         raise TypeError("code '%s' should be a string" % str(code))
@@ -12,21 +18,94 @@
     pc = 0
 
     while pc < code_len:
-        opcode = code[pc]
+        opcode = ord(code[pc])
         pc += 1
 
         if opcode == PUSH:
-            stack.append(ord(code[pc]))
+            stack.append( char2int(code[pc]) )
             pc += 1
 
         elif opcode == POP:
             stack.pop()
 
+        elif opcode == SWAP:
+            a, b = stack.pop(), stack.pop()
+            stack.append(a)
+            stack.append(b)
+
+        elif opcode == ROT: #rotate stack top to somewhere below
+            r = char2int(code[pc])
+            if r > 1:
+                i = len(stack) - r
+                if i < 0:
+                    raise IndexError
+                stack.insert( i, stack.pop() )
+            pc += 1
+
+        elif opcode == PICK:
+            stack.append( stack[-1 - char2int(code[pc])] )
+            pc += 1
+
+        elif opcode == PUT:
+            stack[-1 - char2int(code[pc])] = stack.pop()
+            pc += 1
+
         elif opcode == ADD:
-            stack.append( stack.pop() + stack.pop() )
+            a, b = stack.pop(), stack.pop()
+            stack.append( b + a )
+
+        elif opcode == SUB:
+            a, b = stack.pop(), stack.pop()
+            stack.append( b - a )
+
+        elif opcode == MUL:
+            a, b = stack.pop(), stack.pop()
+            stack.append( b * a )
+
+        elif opcode == DIV:
+            a, b = stack.pop(), stack.pop()
+            stack.append( b / a )
+
+        elif opcode == EQ:
+            a, b = stack.pop(), stack.pop()
+            stack.append( b == a )
+
+        elif opcode == NE:
+            a, b = stack.pop(), stack.pop()
+            stack.append( b != a )
+
+        elif opcode == LT:
+            a, b = stack.pop(), stack.pop()
+            stack.append( b <  a )
+
+        elif opcode == LE:
+            a, b = stack.pop(), stack.pop()
+            stack.append( b <= a )
+
+        elif opcode == GT:
+            a, b = stack.pop(), stack.pop()
+            stack.append( b >  a )
+
+        elif opcode == GE:
+            a, b = stack.pop(), stack.pop()
+            stack.append( b >= a )
+
+        elif opcode == BR_COND:
+            if stack.pop():
+                pc += char2int(code[pc])
+            pc += 1
+
+        elif opcode == CALL:
+            stack.append( pc+1 )
+            pc += char2int(code[pc]) + 1
+
+        elif opcode == RETURN:
+            pc = stack.pop()
+
+        elif opcode == EXIT:
+            break
 
         else:
             raise RuntimeError("unknown opcode: " + str(opcode))
 
     return stack[-1]
-    



More information about the Pypy-commit mailing list