[pypy-svn] r78013 - in pypy/branch/leak-finder/pypy/rlib/rsre: . test

arigo at codespeak.net arigo at codespeak.net
Sat Oct 16 16:38:29 CEST 2010


Author: arigo
Date: Sat Oct 16 16:38:26 2010
New Revision: 78013

Added:
   pypy/branch/leak-finder/pypy/rlib/rsre/test/conftest.py
   pypy/branch/leak-finder/pypy/rlib/rsre/test/test_zjit.py
Modified:
   pypy/branch/leak-finder/pypy/rlib/rsre/rsre_core.py
Log:
In-progress.  Start with some tests.


Modified: pypy/branch/leak-finder/pypy/rlib/rsre/rsre_core.py
==============================================================================
--- pypy/branch/leak-finder/pypy/rlib/rsre/rsre_core.py	(original)
+++ pypy/branch/leak-finder/pypy/rlib/rsre/rsre_core.py	Sat Oct 16 16:38:26 2010
@@ -4,6 +4,7 @@
 from pypy.rlib.rsre import rsre_char
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.rlib.objectmodel import we_are_translated
+from pypy.rlib import jit
 
 
 OPCODE_FAILURE            = 0
@@ -56,15 +57,18 @@
     _seen_specname[specname] = True
     # Install a copy of the function under the name '_spec_funcname' in each
     # concrete subclass
+    specialized_methods = []
     for prefix, concreteclass in [('str', StrMatchContext),
                                   ('uni', UnicodeMatchContext)]:
         newfunc = func_with_new_name(func, prefix + specname)
         assert not hasattr(concreteclass, specname)
         setattr(concreteclass, specname, newfunc)
+        specialized_methods.append(newfunc)
     # Return a dispatcher function, specialized on the exact type of 'ctx'
     def dispatch(ctx, *args):
         return getattr(ctx, specname)(*args)
     dispatch._annspecialcase_ = 'specialize:argtype(0)'
+    dispatch._specialized_methods_ = specialized_methods
     return dispatch
 
 # ____________________________________________________________
@@ -75,6 +79,7 @@
 
 class AbstractMatchContext(object):
     """Abstract base class"""
+    _immutable_fields_ = ['pattern[*]', 'flags']
     match_start = 0
     match_end = 0
     match_marks = None
@@ -238,6 +243,7 @@
         self.start_ptr = ptr
         self.start_marks = marks
 
+    @jit.unroll_safe
     def find_first_result(self, ctx):
         ppos = self.ppos
         while ctx.pat(ppos):
@@ -250,6 +256,8 @@
     find_next_result = find_first_result
 
 class RepeatOneMatchResult(MatchResult):
+    jitdriver = jit.JitDriver(greens=['nextppos', 'pattern'],
+                              reds=['ptr', 'self', 'ctx'])
 
     def __init__(self, nextppos, minptr, ptr, marks):
         self.nextppos = nextppos
@@ -259,8 +267,18 @@
 
     def find_first_result(self, ctx):
         ptr = self.start_ptr
+        nextppos = self.nextppos
         while ptr >= self.minptr:
-            result = sre_match(ctx, self.nextppos, ptr, self.start_marks)
+            #
+            pattern = ctx.pattern
+            self.jitdriver.can_enter_jit(self=self, ptr=ptr, ctx=ctx,
+                                         nextppos=nextppos, pattern=pattern)
+            self.jitdriver.jit_merge_point(self=self, ptr=ptr, ctx=ctx,
+                                           nextppos=nextppos, pattern=pattern)
+            if jit.we_are_jitted():
+                ctx.pattern = pattern
+            #
+            result = sre_match(ctx, nextppos, ptr, self.start_marks)
             ptr -= 1
             if result is not None:
                 self.subresult = result
@@ -270,6 +288,8 @@
 
 
 class MinRepeatOneMatchResult(MatchResult):
+    jitdriver = jit.JitDriver(greens=['nextppos', 'ppos3', 'pattern'],
+                              reds=['ptr', 'self', 'ctx'])
 
     def __init__(self, nextppos, ppos3, maxptr, ptr, marks):
         self.nextppos = nextppos
@@ -280,27 +300,39 @@
 
     def find_first_result(self, ctx):
         ptr = self.start_ptr
+        nextppos = self.nextppos
+        ppos3 = self.ppos3
         while ptr <= self.maxptr:
-            result = sre_match(ctx, self.nextppos, ptr, self.start_marks)
+            #
+            pattern = ctx.pattern
+            self.jitdriver.can_enter_jit(self=self, ptr=ptr, ctx=ctx,
+                                         nextppos=nextppos, pattern=pattern,
+                                         ppos3=ppos3)
+            self.jitdriver.jit_merge_point(self=self, ptr=ptr, ctx=ctx,
+                                           nextppos=nextppos, pattern=pattern,
+                                           ppos3=ppos3)
+            if jit.we_are_jitted():
+                ctx.pattern = pattern
+            #
+            result = sre_match(ctx, nextppos, ptr, self.start_marks)
             if result is not None:
                 self.subresult = result
                 self.start_ptr = ptr
                 return self
-            if not self.next_char_ok(ctx, ptr):
+            if not self.next_char_ok(ctx, ptr, ppos3):
                 break
             ptr += 1
 
     def find_next_result(self, ctx):
         ptr = self.start_ptr
-        if not self.next_char_ok(ctx, ptr):
+        if not self.next_char_ok(ctx, ptr, self.ppos3):
             return
         self.start_ptr = ptr + 1
         return self.find_first_result(ctx)
 
-    def next_char_ok(self, ctx, ptr):
+    def next_char_ok(self, ctx, ptr, ppos):
         if ptr == ctx.end:
             return False
-        ppos = self.ppos3
         op = ctx.pat(ppos)
         for op1, (checkerfn, _) in unroll_char_checker:
             if op1 == op:
@@ -429,6 +461,7 @@
 # ____________________________________________________________
 
 @specializectx
+ at jit.unroll_safe
 def sre_match(ctx, ppos, ptr, marks):
     """Returns either None or a MatchResult object.  Usually we only need
     the first result, but there is the case of REPEAT...UNTIL where we

Added: pypy/branch/leak-finder/pypy/rlib/rsre/test/conftest.py
==============================================================================
--- (empty file)
+++ pypy/branch/leak-finder/pypy/rlib/rsre/test/conftest.py	Sat Oct 16 16:38:26 2010
@@ -0,0 +1,5 @@
+# import the option --viewloops from the JIT
+
+def pytest_addoption(parser):
+    from pypy.jit.conftest import pytest_addoption
+    pytest_addoption(parser)

Added: pypy/branch/leak-finder/pypy/rlib/rsre/test/test_zjit.py
==============================================================================
--- (empty file)
+++ pypy/branch/leak-finder/pypy/rlib/rsre/test/test_zjit.py	Sat Oct 16 16:38:26 2010
@@ -0,0 +1,69 @@
+from pypy.jit.metainterp.test import test_basic
+from pypy.rlib.nonconst import NonConstant
+from pypy.rlib.debug import make_sure_not_modified
+from pypy.rlib.rsre.test.test_match import get_code
+from pypy.rlib.rsre import rsre_core
+from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.annlowlevel import llstr, hlstr
+
+def entrypoint1(r, string):
+    r = array2list(r)
+    string = hlstr(string)
+    make_sure_not_modified(r)
+    match = rsre_core.match(r, string)
+    if match is None:
+        return -1
+    else:
+        return match.match_end
+
+def list2array(lst):
+    a = lltype.malloc(lltype.GcArray(lltype.Signed), len(lst))
+    for i, x in enumerate(lst):
+        a[i] = x
+    return a
+
+def array2list(a):
+    return [a[i] for i in range(len(a))]
+
+
+def test_jit_unroll_safe():
+    # test that the decorators are applied in the right order
+    assert not hasattr(rsre_core.sre_match, '_jit_unroll_safe_')
+    for m in rsre_core.sre_match._specialized_methods_:
+        assert m._jit_unroll_safe_
+
+
+class TestJitRSre(test_basic.LLJitMixin):
+
+    def meta_interp_match(self, pattern, string):
+        r = get_code(pattern)
+        return self.meta_interp(entrypoint1, [list2array(r), llstr(string)],
+                                listcomp=True, backendopt=True)
+
+    def test_simple_match_1(self):
+        res = self.meta_interp_match(r"ab*bbbbbbbc", "abbbbbbbbbcdef")
+        assert res == 11
+
+    def test_simple_match_2(self):
+        res = self.meta_interp_match(r".*abc", "xxabcyyyyyyyyyyyyy")
+        assert res == 5
+
+    def test_match_minrepeat_1(self):
+        res = self.meta_interp_match(r".*?abc", "xxxxxxxxxxxxxxabc")
+        assert res == 17
+
+    #def test_match_maxuntil_1(self):
+    #    res = self.meta_interp_match(r"(ab)*c", "ababababababababc")
+    #    assert res == 17
+
+    def test_branch_1(self):
+        res = self.meta_interp_match(r".*?(ab|x)c", "xxxxxxxxxxxxxxabc")
+        assert res == 17
+
+    def test_match_minrepeat_2(self):
+        s = ("xxxxxxxxxxabbbbbbbbbb" +
+             "xxxxxxxxxxabbbbbbbbbb" +
+             "xxxxxxxxxxabbbbbbbbbb" +
+             "xxxxxxxxxxabbbbbbbbbbc")
+        res = self.meta_interp_match(r".*?ab+?c", s)
+        assert res == len(s)



More information about the Pypy-commit mailing list