Author: Richard Plangger <[email protected]>
Branch: gcstress-hypothesis
Changeset: r82666:f2615fd00d55
Date: 2016-03-02 22:11 +0100
http://bitbucket.org/pypy/pypy/changeset/f2615fd00d55/
Log: moved out test test into new branch
diff --git a/rpython/jit/backend/llsupport/tl/__init__.py
b/rpython/jit/backend/llsupport/tl/__init__.py
new file mode 100644
diff --git a/rpython/jit/backend/llsupport/tl/code.py
b/rpython/jit/backend/llsupport/tl/code.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/tl/code.py
@@ -0,0 +1,216 @@
+
+import struct
+
+class ByteCode(object):
+ def encode(self, ctx):
+ ctx.append_byte(self.BYTE_CODE)
+
+ @classmethod
+ def create_from(self, draw, get_strategy_for):
+ pt = getattr(self.__init__, '_param_types', [])
+ return self(*[draw(get_strategy_for(t)) for t in pt])
+
+_c = 0
+
+LIST_TYP = 'l'
+INT_TYP = 'i'
+OBJ_TYP = 'o'
+STR_TYP = 's'
+VAL_TYP = 'v' # either one of the earlier
+
+all_types = [INT_TYP, LIST_TYP, STR_TYP] # TODO OBJ_TYP
+
+SHORT_TYP = 'h'
+BYTE_TYP = 'b'
+COND_TYP = 'c'
+IDX_TYP = 'x'
+
+
+def unique_code():
+ global _c
+ v = _c
+ _c = v + 1
+ return v
+
+class Context(object):
+ def __init__(self):
+ self.consts = {}
+ self.const_idx = 0
+ self.bytecode = []
+
+ def append_byte(self, byte):
+ self.bytecode.append(('b', byte))
+
+ def get_byte(self, i):
+ typ, byte = self.bytecode[i]
+ assert typ == 'b'
+ return byte
+
+ def get_short(self, i):
+ typ, int = self.bytecode[i]
+ assert typ == 'h'
+ return int
+
+ def append_short(self, byte):
+ self.bytecode.append(('h', byte))
+
+ def append_int(self, byte):
+ self.bytecode.append(('i', byte))
+
+ def const_str(self, str):
+ self.consts[self.const_idx] = str
+ self.append_short(self.const_idx)
+ self.const_idx += 1
+
+ def to_string(self):
+ code = []
+ for typ, nmr in self.bytecode:
+ code.append(struct.pack(typ, nmr))
+ return ''.join(code)
+
+ def transform(self, code_objs):
+ for code_obj in code_objs:
+ code_obj.encode(self)
+
+ return self.to_string(), self.consts
+
+
+def requires_stack(*types):
+ def method(clazz):
+ clazz._stack_types = tuple(types)
+ return clazz
+ return method
+
+def leaves_on_stack(*types):
+ def method(clazz):
+ clazz._return_on_stack_types = tuple(types)
+ return clazz
+ return method
+
+
+def requires_param(*types):
+ def method(m):
+ m._param_types = tuple(types)
+ return m
+ return method
+
+@requires_stack()
+@leaves_on_stack(INT_TYP)
+class PutInt(ByteCode):
+ BYTE_CODE = unique_code()
+ @requires_param(INT_TYP)
+ def __init__(self, value):
+ self.integral = value
+ def encode(self, ctx):
+ ctx.append_byte(self.BYTE_CODE)
+ ctx.append_int(self.integral)
+
+@requires_stack(INT_TYP, INT_TYP)
+@leaves_on_stack(INT_TYP)
+class CompareInt(ByteCode):
+ BYTE_CODE = unique_code()
+ def __init__(self):
+ pass
+
+@requires_stack()
+@leaves_on_stack(STR_TYP)
+class LoadStr(ByteCode):
+ BYTE_CODE = unique_code()
+ @requires_param(STR_TYP)
+ def __init__(self, string):
+ self.string = string
+ def encode(self, ctx):
+ ctx.append_byte(self.BYTE_CODE)
+ ctx.const_str(self.string)
+
+@requires_stack(STR_TYP, STR_TYP)
+@leaves_on_stack(STR_TYP)
+class AddStr(ByteCode):
+ BYTE_CODE = unique_code()
+ def __init__(self):
+ pass
+
+@requires_stack(LIST_TYP, LIST_TYP)
+@leaves_on_stack(LIST_TYP)
+class AddList(ByteCode):
+ BYTE_CODE = unique_code()
+ def __init__(self):
+ pass
+
+@requires_stack()
+@leaves_on_stack(LIST_TYP)
+class CreateList(ByteCode):
+ BYTE_CODE = unique_code()
+ @requires_param(BYTE_TYP)
+ def __init__(self, size=8):
+ self.size = size
+ def encode(self, ctx):
+ ctx.append_byte(self.BYTE_CODE)
+ ctx.append_short(self.size)
+
+@requires_stack(LIST_TYP, IDX_TYP, INT_TYP) # TODO VAL_TYP
+@leaves_on_stack(LIST_TYP)
+class InsertList(ByteCode):
+ BYTE_CODE = unique_code()
+ def __init__(self):
+ pass
+
+@requires_stack(LIST_TYP, IDX_TYP)
+@leaves_on_stack(LIST_TYP)
+class DelList(ByteCode):
+ BYTE_CODE = unique_code()
+ def __init__(self):
+ pass
+
+@requires_stack(LIST_TYP, INT_TYP) # TODO VAL_TYP)
+@leaves_on_stack(LIST_TYP)
+class AppendList(ByteCode):
+ BYTE_CODE = unique_code()
+ def __init__(self):
+ pass
+
+
+# remove comment one by one!
+
+#@requires_stack()
+#@leaves_on_stack(INT_TYP)
+#class CondJump(ByteCode):
+# BYTE_CODE = unique_code()
+#
+# COND_EQ = 0
+# COND_LT = 1
+# COND_GT = 2
+# COND_LE = 3
+# COND_GE = 4
+#
+# @requires_param(COND_TYP)
+# def __init__(self, cond):
+# self.cond = cond
+#
+# def encode(self, ctx):
+# ctx.append_byte(self.BYTE_CODE)
+# ctx.append_byte(self.cond)
+#
+#@requires_stack()
+#@leaves_on_stack()
+#class Jump(ByteCode):
+# BYTE_CODE = unique_code()
+# def __init__(self):
+# pass
+#
+
+#@requires_stack(LIST_TYP)
+#@leaves_on_stack(LIST_TYP, INT_TYP)
+#class LenList(ByteCode):
+# BYTE_CODE = unique_code()
+# def __init__(self):
+# pass
+#
+#
+#@requires_stack(INT_TYP) # TODO VAL_TYP)
+#@leaves_on_stack()
+#class ReturnFrame(ByteCode):
+# BYTE_CODE = unique_code()
+# def __init__(self):
+# pass
+#
diff --git a/rpython/jit/backend/llsupport/tl/interp.py
b/rpython/jit/backend/llsupport/tl/interp.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/tl/interp.py
@@ -0,0 +1,126 @@
+from rpython.rlib.rstruct.runpack import runpack
+from rpython.rlib.objectmodel import specialize, always_inline
+from rpython.jit.backend.llsupport.tl import code
+from rpython.jit.backend.llsupport.tl.stack import Stack
+from rpython.rlib import rstring
+
+class W_Root(object):
+ pass
+
+class W_ListObject(W_Root):
+ def __init__(self, items):
+ self.items = items
+
+ def concat(self, space, w_lst):
+ assert isinstance(w_lst, W_ListObject)
+ return space.wrap(self.items + w_lst.items)
+
+class W_IntObject(W_Root):
+ def __init__(self, value):
+ self.value = value
+
+ def compare(self, space, w_int):
+ assert isinstance(w_int, W_IntObject)
+ return space.wrap(self.value - w_int.value)
+
+ def concat(self, space, w_obj):
+ raise NotImplementedError("cannot concat int with object")
+
+class W_StrObject(W_Root):
+ def __init__(self, value):
+ self.value = value
+
+ def concat(self, space, w_str):
+ assert isinstance(w_str, W_StrObject)
+ return space.wrap(self.value + w_str.value)
+
+class Space(object):
+ @specialize.argtype(1)
+ def wrap(self, val):
+ if isinstance(val, W_Root):
+ return val
+ if isinstance(val, int):
+ return W_IntObject(val)
+ if isinstance(val, str):
+ return W_StrObject(val)
+ if isinstance(val, unicode):
+ return W_StrObject(val.encode('utf-8'))
+ if isinstance(val, list):
+ return W_ListObject(val)
+ raise NotImplementedError("cannot handle: " + str(val))
+
+def _read_all_from_file(file):
+ with open(file, 'rb') as fd:
+ return fd.read()
+
+_read_bytecode_from_file = _read_all_from_file
+
+def _read_consts_from_file(file):
+ consts = []
+ bytestring = _read_all_from_file(file)
+ for line in bytestring.splitlines():
+ consts.append(rstring.replace(line, "\\n", "\n"))
+ return consts
+
+def entry_point(argv):
+ bytecode = _read_bytecode_from_file(argv[1])
+ consts = _read_consts_from_file(argv[2])
+ print(bytecode)
+ print(consts)
+ pc = 0
+ end = len(bytecode)
+ stack = Stack(16)
+ space = Space()
+ while pc < end:
+ pc = dispatch_once(space, pc, bytecode, consts, stack)
+ return 0
+
+@always_inline
+def dispatch_once(space, i, bytecode, consts, stack):
+ opcode = ord(bytecode[i])
+ if opcode == code.PutInt.BYTE_CODE:
+ integral = runpack('i', bytecode[i+1:i+5])
+ stack.append(space.wrap(integral))
+ i += 4
+ elif opcode == code.CompareInt.BYTE_CODE:
+ w_int2 = stack.pop()
+ w_int1 = stack.pop()
+ stack.append(w_int1.compare(space, w_int2))
+ elif opcode == code.LoadStr.BYTE_CODE:
+ pos = runpack('h', bytecode[i+1:i+3])
+ w_str = space.wrap(consts[pos])
+ stack.append(w_str)
+ i += 2
+ elif opcode == code.AddStr.BYTE_CODE:
+ w_str2 = stack.pop()
+ w_str1 = stack.pop()
+ stack.append(w_str1.concat(space, w_str2))
+ elif opcode == code.AddList.BYTE_CODE:
+ w_lst2 = stack.pop()
+ w_lst1 = stack.pop()
+ stack.append(w_lst1.concat(space, w_lst2))
+ elif opcode == code.CreateList.BYTE_CODE:
+ size = runpack('h', bytecode[i+1:i+3])
+ stack.append(space.wrap([None] * size))
+ i += 2
+ elif opcode == code.AppendList.BYTE_CODE:
+ w_val = stack.pop()
+ w_lst = stack.peek(0)
+ w_lst.items.append(w_val)
+ elif opcode == code.InsertList.BYTE_CODE:
+ w_val = stack.pop()
+ w_idx = stack.pop()
+ assert isinstance(w_idx, W_IntObject)
+ w_lst = stack.peek(0)
+ w_lst.items[w_idx.value] = w_val
+ # index error, just crash here!
+ elif opcode == code.DelList.BYTE_CODE:
+ w_idx = stack.pop()
+ assert isinstance(w_idx, W_IntObject)
+ w_lst = stack.peek(0)
+ del w_lst.items[w_idx.value]
+ # index error, just crash the machine!!
+ else:
+ print("opcode %d is not implemented" % opcode)
+ raise NotImplementedError
+ return i + 1
diff --git a/rpython/jit/backend/llsupport/tl/stack.py
b/rpython/jit/backend/llsupport/tl/stack.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/tl/stack.py
@@ -0,0 +1,66 @@
+from rpython.rlib.jit import JitDriver, hint, dont_look_inside, promote
+
+class Stack(object):
+ _virtualizable_ = ['stackpos', 'stack[*]']
+
+ def __init__(self, size):
+ self = hint(self, access_directly=True, fresh_virtualizable=True)
+ self.stack = [None] * size
+ self.stackpos = 0 # always store a known-nonneg integer here
+
+ def size(self):
+ return self.stackpos
+
+ def append(self, elem):
+ while len(self.stack) <= self.stackpos:
+ self.stack.append(None)
+ self.stack[self.stackpos] = elem
+ self.stackpos += 1
+
+ def peek(self, i):
+ stackpos = self.stackpos - i - 1
+ if stackpos < 0:
+ raise IndexError
+ return self.stack[stackpos]
+
+ def pop(self):
+ stackpos = self.stackpos - 1
+ if stackpos < 0:
+ raise IndexError
+ self.stackpos = stackpos # always store a known-nonneg integer here
+ return self.stack[stackpos]
+
+ def pick(self, i):
+ n = self.stackpos - i - 1
+ assert n >= 0
+ self.append(self.stack[n])
+
+ def put(self, i):
+ elem = self.pop()
+ n = self.stackpos - i - 1
+ assert n >= 0
+ self.stack[n] = elem
+
+ @dont_look_inside
+ def roll(self, r):
+ if r < -1:
+ i = self.stackpos + r
+ if i < 0:
+ raise IndexError
+ n = self.stackpos - 1
+ assert n >= 0
+ elem = self.stack[n]
+ for j in range(self.stackpos - 2, i - 1, -1):
+ assert j >= 0
+ self.stack[j + 1] = self.stack[j]
+ self.stack[i] = elem
+ elif r > 1:
+ i = self.stackpos - r
+ if i < 0:
+ raise IndexError
+ elem = self.stack[i]
+ for j in range(i, self.stackpos - 1):
+ self.stack[j] = self.stack[j + 1]
+ n = self.stackpos - 1
+ assert n >= 0
+ self.stack[n] = elem
diff --git a/rpython/jit/backend/llsupport/tl/test/__init__.py
b/rpython/jit/backend/llsupport/tl/test/__init__.py
new file mode 100644
diff --git a/rpython/jit/backend/llsupport/tl/test/code_strategies.py
b/rpython/jit/backend/llsupport/tl/test/code_strategies.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/tl/test/code_strategies.py
@@ -0,0 +1,75 @@
+from hypothesis import strategies as st
+from hypothesis.control import assume
+from hypothesis.strategies import defines_strategy, composite
+from rpython.jit.backend.llsupport.tl import code, interp, stack
+from rpython.jit.backend.llsupport.tl.code import (all_types,
+ INT_TYP, STR_TYP, LIST_TYP, SHORT_TYP, BYTE_TYP,
+ COND_TYP, IDX_TYP)
+from hypothesis.searchstrategy.strategies import OneOfStrategy
+from hypothesis.searchstrategy.collections import TupleStrategy
+
+def get_strategy_for(typ):
+ if typ == INT_TYP:
+ return st.integers(min_value=-2**31, max_value=2**31-1)
+ elif typ == IDX_TYP:
+ return st.integers(min_value=-2**31, max_value=2**31-1)
+ elif typ == SHORT_TYP:
+ return st.integers(min_value=-2**15, max_value=2**15-1)
+ elif typ == BYTE_TYP:
+ return st.integers(min_value=-2**7, max_value=2**7-1)
+ elif typ == COND_TYP:
+ return st.integers(min_value=0, max_value=4)
+ elif typ == STR_TYP:
+ return st.text()
+ elif typ == LIST_TYP:
+ return st.lists(elements=st.one_of(st.integers())) # TODO must be
recursive
+ else:
+ raise NotImplementedError("type: " + str(typ))
+
+STD_SPACE = interp.Space()
+
+@composite
+def runtime_stack(draw, clazz):
+ strats = [get_strategy_for(t) for t in clazz._stack_types]
+ stack_obj = stack.Stack(len(strats))
+ for i,strat in enumerate(strats):
+ if clazz._stack_types[i] == IDX_TYP:
+ # it is only valid to access a list with a valid index!
+ w_list = stack_obj.peek(i-1)
+ l = len(w_list.items)
+ assume(l > 0)
+ integrals = st.integers(min_value=0, max_value=l-1)
+ stack_obj.append(STD_SPACE.wrap(draw(integrals)))
+ continue
+ stack_obj.append(STD_SPACE.wrap(draw(strat)))
+ return stack_obj
+
+def byte_code_classes():
+ for name, clazz in code.__dict__.items():
+ if hasattr(clazz, 'BYTE_CODE'):
+ yield clazz
+
+def get_byte_code_class(num):
+ for clazz in byte_code_classes():
+ if clazz.BYTE_CODE == num:
+ return clazz
+ return None
+
+@composite
+def single_bytecode(draw,
+ clazzes=st.sampled_from(byte_code_classes()),
+ integrals=st.integers(), texts=st.text()):
+ clazz = draw(clazzes)
+ inst = clazz.create_from(draw, get_strategy_for)
+ bytecode, consts = code.Context().transform([inst])
+ _stack = draw(runtime_stack(clazz))
+ return bytecode, consts, _stack
+
+@composite
+def bytecode_block(draw,
+ clazzes=st.sampled_from(byte_code_classes()),
+ integrals=st.integers(), texts=st.text()):
+ clazz = draw(clazzes)
+ inst = clazz.create_from(draw, get_strategy_for)
+ bytecode, consts = code.Context().transform([inst])
+ return bytecode, consts
diff --git a/rpython/jit/backend/llsupport/tl/test/test_tl_interp.py
b/rpython/jit/backend/llsupport/tl/test/test_tl_interp.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/tl/test/test_tl_interp.py
@@ -0,0 +1,43 @@
+import py
+from hypothesis import given
+from rpython.jit.backend.llsupport.tl import code, interp
+from rpython.jit.backend.llsupport.tl.stack import Stack
+from rpython.jit.backend.llsupport.tl.test import code_strategies as st
+
+class TestByteCode(object):
+ def test_load_str(self):
+ c = code.Context()
+ code.LoadStr("hello world").encode(c)
+ assert c.consts[0] == "hello world"
+ assert c.get_byte(0) == code.LoadStr.BYTE_CODE
+ assert c.get_short(1) == 0
+
+ def test_str_add(self):
+ c = code.Context()
+ code.LoadStr("hello").encode(c)
+ code.LoadStr("world").encode(c)
+ code.AddStr().encode(c)
+ assert len(c.consts) == 2
+ assert c.get_byte(4) == code.AddStr.BYTE_CODE
+ assert c.get_short(3) == 1
+
+class TestInterp(object):
+ @given(st.single_bytecode())
+ def test_consume_stack(self, args):
+ bytecode, consts, stack = args
+ space = interp.Space()
+ i = interp.dispatch_once(space, 0, bytecode, consts, stack)
+ assert i == len(bytecode)
+ clazz = st.get_byte_code_class(ord(bytecode[0]))
+ assert stack.size() == len(clazz._return_on_stack_types)
+
+ @given(st.bytecode_block())
+ def test_execute_bytecode_block(self, args):
+ bytecode, consts = args
+ space = interp.Space()
+ stack = Stack(16)
+ pc = 0
+ end = len(bytecode)
+ while pc < end:
+ pc = interp.dispatch_once(space, pc, bytecode, consts, stack)
+ assert pc == len(bytecode)
diff --git a/rpython/jit/backend/llsupport/tl/test/zrpy_gc_hypo_test.py
b/rpython/jit/backend/llsupport/tl/test/zrpy_gc_hypo_test.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/llsupport/tl/test/zrpy_gc_hypo_test.py
@@ -0,0 +1,62 @@
+import py
+from hypothesis import given
+from rpython.tool.udir import udir
+from rpython.jit.metainterp.optimize import SpeculativeError
+from rpython.annotator.listdef import s_list_of_strings
+from rpython.translator.translator import TranslationContext
+from rpython.translator.c import genc
+from rpython.jit.backend.llsupport.tl import interp
+from rpython.jit.backend.llsupport.tl.test import code_strategies as st
+
+def persist(type, contents):
+ dir = udir.ensure(type)
+ print "written", type, "to", dir
+ with open(dir.strpath, 'wb') as fd:
+ fd.write(contents)
+ return dir.strpath
+
+def persist_constants(consts):
+ contents = ""
+ for string in consts:
+ contents += string.replace("\n", "\\n") + "\n"
+ return persist('constants', contents)
+
+def persist_bytecode(bc):
+ return persist('bytecode', bc)
+
+class GCHypothesis(object):
+ builder = None
+ def setup_method(self, name):
+ if self.builder:
+ return
+
+ t = TranslationContext()
+ t.config.translation.gc = "incminimark"
+ t.config.translation.gcremovetypeptr = True
+ ann = t.buildannotator()
+ ann.build_types(interp.entry_point, [s_list_of_strings],
main_entry_point=True)
+ rtyper = t.buildrtyper()
+ rtyper.specialize()
+
+ cbuilder = genc.CStandaloneBuilder(t, interp.entry_point, t.config)
+ cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES)
+ cbuilder.compile()
+ # prevent from rebuilding the c object!
+ self.builder = cbuilder
+
+ def execute(self, bytecode, consts):
+ exe = self.builder.executable_name
+ bc_file = persist_bytecode(bytecode)
+ consts_file = persist_constants(consts)
+ args = [bc_file, consts_file]
+ env = {}
+ res = self.builder.translator.platform.execute(exe, args, env=env)
+ return res.returncode, res.out, res.err
+
+ @given(st.bytecode_block())
+ def test_execute_single_bytecode(self, program):
+ bytecode, consts = program
+ result, out, err = self.execute(bytecode, consts)
+ if result != 0:
+ raise Exception(("could not run program. returned %d"
+ " stderr:\n%s\nstdout:\n%s\n") % (result, err,
out))
diff --git a/rpython/jit/backend/x86/test/test_zrpy_gc_hypo.py
b/rpython/jit/backend/x86/test/test_zrpy_gc_hypo.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/x86/test/test_zrpy_gc_hypo.py
@@ -0,0 +1,6 @@
+from rpython.jit.backend.llsupport.tl.test.zrpy_gc_hypo_test import
GCHypothesis
+
+class TestGCHypothesis(GCHypothesis):
+ # runs ../../llsupport/tl/test/zrpy_gc_hypo_test.py
+ gcrootfinder = "shadowstack"
+ gc = "incminimark"
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit