[pypy-commit] pypy resume-refactor: start fighting with strings

fijal noreply at buildbot.pypy.org
Wed Jan 29 16:13:57 CET 2014


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: resume-refactor
Changeset: r68991:07f41e9e2678
Date: 2014-01-29 14:52 +0100
http://bitbucket.org/pypy/pypy/changeset/07f41e9e2678/

Log:	start fighting with strings

diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -44,24 +44,20 @@
         return Position(self.numbering[self.mapping(box)])
 
     def process(self, op):
-        getattr(self, 'process_' + op.getopname())(op)
+        func = getattr(self, 'process_' + op.getopname(), None)
+        if func is not None:
+            func(op)
         ResumeBuilder.process(self, op)
 
-    def process_enter_frame(self, op):
-        pass
-
-    def process_leave_frame(self, op):
-        pass
-
-    def process_resume_set_pc(self, op):
-        pass
-
-    def process_resume_new_with_vtable(self, op):
-        pass
-
     def process_resume_setfield_gc(self, op):
         self._add_box_to_numbering(op.getarg(1))
 
+    def process_resume_concatstr(self, op):
+        self._add_box_to_numbering(op.getarg(0))
+        self._add_box_to_numbering(op.getarg(1))
+
+    process_resume_concatunicode = process_resume_concatstr
+        
     def _add_box_to_numbering(self, box):
         if isinstance(box, Const):
             return
@@ -70,9 +66,6 @@
 
     def process_resume_put(self, op):
         self._add_box_to_numbering(op.getarg(0))
-
-    def process_resume_clear(self, op):
-        pass
     
 class LLTrace(object):
     has_been_freed = False
diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py
--- a/rpython/jit/metainterp/optimizeopt/virtualize.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualize.py
@@ -503,6 +503,7 @@
         return vvalue
 
     def make_varray(self, arraydescr, size, box, source_op=None):
+        xxx
         if arraydescr.is_array_of_structs():
             vvalue = VArrayStructValue(arraydescr, size, box, source_op)
         else:
@@ -519,12 +520,14 @@
         return vvalue
 
     def make_virtual_raw_memory(self, size, box, source_op):
+        xxx
         logops = self.optimizer.loop.logops
         vvalue = VRawBufferValue(self.optimizer.cpu, logops, size, box, source_op)
         self.make_equal_to(box, vvalue)
         return vvalue
 
     def make_virtual_raw_slice(self, rawbuffer_value, offset, box, source_op):
+        xxx
         vvalue = VRawSliceValue(rawbuffer_value, offset, box, source_op)
         self.make_equal_to(box, vvalue)
         return vvalue
diff --git a/rpython/jit/metainterp/optimizeopt/vstring.py b/rpython/jit/metainterp/optimizeopt/vstring.py
--- a/rpython/jit/metainterp/optimizeopt/vstring.py
+++ b/rpython/jit/metainterp/optimizeopt/vstring.py
@@ -19,6 +19,7 @@
 class StrOrUnicode(object):
     def __init__(self, LLTYPE, hlstr, emptystr, chr,
                  NEWSTR, STRLEN, STRGETITEM, STRSETITEM, COPYSTRCONTENT,
+                 RESUME_NEW, RESUME_CONCAT,
                  OS_offset):
         self.LLTYPE = LLTYPE
         self.hlstr = hlstr
@@ -29,6 +30,8 @@
         self.STRGETITEM = STRGETITEM
         self.STRSETITEM = STRSETITEM
         self.COPYSTRCONTENT = COPYSTRCONTENT
+        self.RESUME_NEW = RESUME_NEW
+        self.RESUME_CONCAT = RESUME_CONCAT
         self.OS_offset = OS_offset
 
     def _freeze_(self):
@@ -36,10 +39,12 @@
 
 mode_string = StrOrUnicode(rstr.STR, annlowlevel.hlstr, '', chr,
                            rop.NEWSTR, rop.STRLEN, rop.STRGETITEM,
-                           rop.STRSETITEM, rop.COPYSTRCONTENT, 0)
+                           rop.STRSETITEM, rop.COPYSTRCONTENT,
+                           rop.RESUME_NEWSTR, rop.RESUME_CONCATSTR, 0)
 mode_unicode = StrOrUnicode(rstr.UNICODE, annlowlevel.hlunicode, u'', unichr,
                             rop.NEWUNICODE, rop.UNICODELEN, rop.UNICODEGETITEM,
                             rop.UNICODESETITEM, rop.COPYUNICODECONTENT,
+                            rop.RESUME_NEWUNICODE, rop.RESUME_CONCATUNICODE,
                             EffectInfo._OS_offset_uni)
 
 # ____________________________________________________________
@@ -390,17 +395,22 @@
     def new(self):
         return OptString()
 
-    def make_vstring_plain(self, box, source_op, mode):
+    def make_vstring_plain(self, box, source_op, mode, length):
         vvalue = VStringPlainValue(box, source_op, mode)
+        vvalue.setup(length)
+        self.optimizer.resumebuilder.new_vstring(vvalue, length, mode)
         self.make_equal_to(box, vvalue)
         return vvalue
 
-    def make_vstring_concat(self, box, source_op, mode):
+    def make_vstring_concat(self, box, source_op, mode, left, right):
         vvalue = VStringConcatValue(box, source_op, mode)
+        vvalue.setup(left, right)
+        self.optimizer.resumebuilder.vstring_concat(vvalue, left, right, mode)
         self.make_equal_to(box, vvalue)
         return vvalue
 
     def make_vstring_slice(self, box, source_op, mode):
+        xxx
         vvalue = VStringSliceValue(box, source_op, mode)
         self.make_equal_to(box, vvalue)
         return vvalue
@@ -417,8 +427,8 @@
             # build a new one with the ConstInt argument
             if not isinstance(op.getarg(0), ConstInt):
                 op = ResOperation(mode.NEWSTR, [length_box], op.result)
-            vvalue = self.make_vstring_plain(op.result, op, mode)
-            vvalue.setup(length_box.getint())
+            self.make_vstring_plain(op.result, op, mode,
+                                             length_box.getint())
         else:
             self.getvalue(op.result).ensure_nonnull()
             self.emit_operation(op)
@@ -430,7 +440,10 @@
         if value.is_virtual() and isinstance(value, VStringPlainValue):
             indexbox = self.get_constant_box(op.getarg(1))
             if indexbox is not None:
-                value.setitem(indexbox.getint(), self.getvalue(op.getarg(2)))
+                index = indexbox.getint()
+                varg = self.getvalue(op.getarg(2))
+                value.setitem(index, varg)
+                self.optimizer.resumebuilder.strsetitem(value, varg)
                 return
         value.ensure_nonnull()
         self.emit_operation(op)
@@ -592,8 +605,7 @@
         vright = self.getvalue(op.getarg(2))
         vleft.ensure_nonnull()
         vright.ensure_nonnull()
-        value = self.make_vstring_concat(op.result, op, mode)
-        value.setup(vleft, vright)
+        self.make_vstring_concat(op.result, op, mode, vleft, vright)
         return True
 
     def opt_call_stroruni_STR_SLICE(self, op, mode):
diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -480,6 +480,9 @@
     'RESUME_NEW_ARRAY/1d',
     'RESUME_NEWSTR/1',
     'RESUME_NEWUNICODE/1',
+    'RESUME_CONCATSTR/2',
+    'RESUME_CONCATUNICODE/2',
+    'RESUME_STRSETITEM/2',
     'RESUME_SETFIELD_GC/2d',
     'RESUME_SET_PC/1',
     'RESUME_CLEAR/2',
diff --git a/rpython/jit/resume/backend.py b/rpython/jit/resume/backend.py
--- a/rpython/jit/resume/backend.py
+++ b/rpython/jit/resume/backend.py
@@ -1,10 +1,31 @@
 
 from rpython.jit.metainterp.resoperation import rop
-from rpython.jit.metainterp.history import Box, Const
+from rpython.jit.metainterp.history import Box, Const, AbstractDescr
 from rpython.jit.resume.rescode import ResumeBytecodeBuilder, TAGBOX,\
      ResumeBytecode, TAGVIRTUAL
 from rpython.jit.codewriter.jitcode import JitCode
 
+class DescrForStr(AbstractDescr):
+    pass
+
+left_descr = DescrForStr()
+right_descr = DescrForStr()
+
+class BaseDeps(object):
+    pass
+
+class DepsFields(BaseDeps):
+    def __init__(self):
+        self.fields = {}
+
+class DepsConcat(BaseDeps):
+    def __init__(self, left, right):
+        self.left = left
+        self.right = right
+
+class DepsArray(BaseDeps):
+    def __init__(self, size):
+        self.l = [None] * size
 
 class LivenessAnalyzer(object):
     def __init__(self):
@@ -26,13 +47,22 @@
         self.framestack[framepos][frontend_pos] = None
 
     def resume_new(self, result, descr):
-        self.deps[result] = {}
+        self.deps[result] = DepsFields()
+
+    def resume_newunicode(self, result, length):
+        self.deps[result] = DepsArray(length)
+
+    def resume_concatunicode(self, result, left, right):
+        self.deps[result] = DepsConcat(left, right)
 
     def resume_new_with_vtable(self, result, klass):
-        self.deps[result] = {}
+        self.deps[result] = DepsFields()
 
     def resume_setfield_gc(self, arg0, arg1, descr):
-        self.deps[arg0][descr] = arg1
+        self.deps[arg0].fields[descr] = arg1
+
+    def resume_strsetitem(self, arg0, arg1):
+        xxx
 
     def resume_set_pc(self, pc):
         pass
@@ -64,6 +94,16 @@
             elif op.getopnum() == rop.RESUME_CLEAR:
                 self.resume_clear(op.getarg(0).getint(),
                                   op.getarg(1).getint())
+            elif op.getopnum() == rop.RESUME_NEWSTR:
+                xxx
+            elif op.getopnum() == rop.RESUME_NEWUNICODE:
+                self.resume_newunicode(op.result, op.getarg(0).getint())
+            elif op.getopnum() == rop.RESUME_CONCATSTR:
+                xxx
+            elif op.getopnum() == rop.RESUME_CONCATUNICODE:
+                self.resume_concatunicode(op.result, op.getarg(0), op.getarg(1))
+            elif op.getopnum() == rop.RESUME_STRSETITEM:
+                self.resume_strsetitem(op.getarg(0), op.getarg(1))
             elif not op.is_resume():
                 pos += 1
                 continue
@@ -150,6 +190,20 @@
         elif op.getopnum() == rop.RESUME_CLEAR:
             self.builder.resume_clear(op.getarg(0).getint(),
                                       op.getarg(1).getint())
+        elif op.getopnum() == rop.RESUME_NEWSTR:
+            xxx
+        elif op.getopnum() == rop.RESUME_NEWUNICODE:
+            v_pos = len(self.virtuals)
+            self.virtuals[op.result] = v_pos
+            self.builder.resume_newunicode(v_pos, op.getarg(0).getint())
+        elif op.getopnum() == rop.RESUME_CONCATSTR:
+            xxx
+        elif op.getopnum() == rop.RESUME_CONCATUNICODE:
+            v_pos = len(self.virtuals)
+            self.virtuals[op.result] = v_pos
+            leftpos = self.get_box_pos(op.getarg(0))
+            rightpos = self.get_box_pos(op.getarg(0))
+            self.builder.resume_concatunicode(v_pos, leftpos, rightpos)
         else:
             raise Exception("strange operation")
 
diff --git a/rpython/jit/resume/frontend.py b/rpython/jit/resume/frontend.py
--- a/rpython/jit/resume/frontend.py
+++ b/rpython/jit/resume/frontend.py
@@ -76,11 +76,9 @@
             return self.virtuals_cache[index]
         except KeyError:
             pass
-        val = self.virtuals[index].allocate_direct(self.cpu)
+        val = self.virtuals[index].allocate_direct(self, self.cpu)
         self.virtuals_cache[index] = val
-        fields = self.virtuals[index].fields
-        for fielddescr, encoded_field_pos in fields.iteritems():
-            self.setfield_gc(val, encoded_field_pos, fielddescr)
+        self.virtuals[index].populate_fields(val, self)
         return val
 
     def setfield_gc(self, struct, encoded_field_pos, fielddescr):
diff --git a/rpython/jit/resume/optimizer.py b/rpython/jit/resume/optimizer.py
--- a/rpython/jit/resume/optimizer.py
+++ b/rpython/jit/resume/optimizer.py
@@ -51,10 +51,6 @@
         else:
             self.opt.emit_operation(op)
 
-    def new_virtual(self, box):
-        xxx
-        self.optimizer.emit_operation(rop.RESUME_NEW)
-
     def new_virtual_with_vtable(self, box, vtable, vvalue):
         virtualbox = BoxPtr()
         op = ResOperation(rop.RESUME_NEW_WITH_VTABLE, [vtable], virtualbox)
@@ -67,6 +63,26 @@
         op = ResOperation(rop.RESUME_NEW, [], newbox, descr=structdescr)
         self.opt._newoperations.append(op)
 
+    def new_vstring(self, vstring, lgt, mode):
+        newbox = BoxPtr()
+        vstring.resume_box = newbox
+        op = ResOperation(mode.RESUME_NEW, [ConstInt(lgt)], newbox)
+        self.opt._newoperations.append(op)
+
+    def vstring_concat(self, vstring, left, right, mode):
+        leftbox = left.get_resume_box()
+        rightbox = right.get_resume_box()
+        newbox = BoxPtr()
+        vstring.resume_box = newbox
+        op = ResOperation(mode.RESUME_CONCAT, [leftbox, rightbox], newbox)
+        self.opt._newoperations.append(op)
+
+    def strsetitem(self, vstring, varg):
+        argbox = varg.get_resume_box()
+        op = ResOperation(rop.RESUME_STRSETITEM, [vstring.get_resume_box(),
+                                                     argbox], None)
+        self.opt._newoperations.append(op)
+
     def setfield(self, box, fieldbox, descr):
         op = ResOperation(rop.RESUME_SETFIELD_GC, [box, fieldbox], None,
                           descr=descr)
diff --git a/rpython/jit/resume/reader.py b/rpython/jit/resume/reader.py
--- a/rpython/jit/resume/reader.py
+++ b/rpython/jit/resume/reader.py
@@ -1,4 +1,7 @@
 
+from rpython.rtyper.lltypesystem import lltype, rstr, llmemory
+
+from rpython.jit.codewriter.effectinfo import EffectInfo
 from rpython.jit.metainterp.resoperation import rop
 from rpython.jit.metainterp.history import ConstInt
 from rpython.jit.codewriter import heaptracker
@@ -11,9 +14,16 @@
         self.pc = -1
 
 class BaseVirtual(object):
-    pass
+    def populate_fields(self, reader):
+        pass
 
-class VirtualStruct(BaseVirtual):
+class BaseVirtualStruct(BaseVirtual):
+    def populate_fields(self, val, reader):
+        fields = self.fields
+        for fielddescr, encoded_field_pos in fields.iteritems():
+            reader.setfield_gc(val, encoded_field_pos, fielddescr)
+
+class VirtualStruct(BaseVirtualStruct):
     def __init__(self, pos, descr):
         self.pos = pos
         self.fields = {}
@@ -22,10 +32,10 @@
     def allocate_box(self, metainterp):
         return metainterp.execute_and_record(rop.NEW, self.descr)
 
-    def allocate_direct(self, cpu):
+    def allocate_direct(self, reader, cpu):
         return cpu.bh_new(self.descr)
     
-class VirtualWithVtable(BaseVirtual):
+class VirtualWithVtable(BaseVirtualStruct):
     def __init__(self, pos, const_class):
         self.pos = pos
         self.const_class = const_class
@@ -35,10 +45,37 @@
         return metainterp.execute_and_record(rop.NEW_WITH_VTABLE, None,
                                              ConstInt(self.const_class))
 
-    def allocate_direct(self, cpu):
+    def allocate_direct(self, reader, cpu):
         descr = heaptracker.vtable2descr(cpu, self.const_class)
         return cpu.bh_new_with_vtable(self.const_class, descr)
 
+class VirtualStr(BaseVirtual):
+    def __init__(self, pos, lgt, mode):
+        self.pos = pos
+        self.lgt = lgt
+        self.mode = mode
+
+class VirtualConcat(BaseVirtual):
+    def __init__(self, pos, left, right, mode):
+        self.pos = pos
+        self.left = left
+        self.right = right
+        self.mode = mode
+
+    def allocate_direct(self, reader, cpu):
+        leftval = reader.getref(self.left)
+        rightval = reader.getref(self.right)
+        cic = reader.staticdata.callinfocollection
+        if self.mode == 'u':
+            funcptr = cic.funcptr_for_oopspec(EffectInfo.OS_UNI_CONCAT)
+            str1 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), leftval)
+            str2 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), rightval)
+            result = funcptr(str1, str2)
+            return lltype.cast_opaque_ptr(llmemory.GCREF, result)
+        else:
+            xxx
+        xxx
+
 class AbstractResumeReader(object):
     """ A resume reader that can follow resume until given point. Consult
     the concrete classes for details
@@ -73,6 +110,22 @@
         v = VirtualStruct(v_pos, descr)
         self._add_to_virtuals(v, v_pos)
 
+    def resume_newstr(self, v_pos, lgt):
+        v = VirtualStr(v_pos, lgt, 's')
+        self._add_to_virtuals(v, v_pos)
+
+    def resume_newunicode(self, v_pos, lgt):
+        v = VirtualStr(v_pos, lgt, 'u')
+        self._add_to_virtuals(v, v_pos)
+
+    def resume_concatstr(self, v_pos, leftpos, rightpos):
+        v = VirtualConcat(v_pos, leftpos, rightpos, 's')
+        self._add_to_virtuals(v, v_pos)
+
+    def resume_concatunicode(self, v_pos, leftpos, rightpos):
+        v = VirtualConcat(v_pos, leftpos, rightpos, 'u')
+        self._add_to_virtuals(v, v_pos)
+
     def resume_new_with_vtable(self, v_pos, c_const_class):
         const_class = c_const_class.getint()
         v = VirtualWithVtable(v_pos, const_class)
@@ -153,6 +206,21 @@
                 pc = self.read_short(pos + 1)
                 self.resume_set_pc(pc)
                 pos += 3
+            elif op == rescode.RESUME_NEWSTR:
+                xxx
+            elif op == rescode.RESUME_NEWUNICODE:
+                v_pos = self.read_short(pos + 1)
+                lgt = self.read(pos + 3)
+                self.resume_newunicode(v_pos, lgt)
+                pos += 4
+            elif op == rescode.RESUME_CONCATSTR:
+                xxx
+            elif op == rescode.RESUME_CONCATUNICODE:
+                v_pos = self.read_short(pos + 1)
+                left = self.read_short(pos + 3)
+                right = self.read_short(pos + 5)
+                self.resume_concatunicode(v_pos, left, right)
+                pos += 7
             else:
                 xxx
         self.bytecode = None
@@ -179,6 +247,18 @@
     def resume_clear(self, frame_pos, pos_in_frame):
         self.l.append("resume_clear %d %d" % (frame_pos, pos_in_frame))
 
+    def resume_newstr(self, v_pos, lgt):
+        xxx
+
+    def resume_newunicode(self, v_pos, lgt):
+        xxx
+
+    def resume_concatstr(self, v_pos, leftpos, rightpos):
+        xxx
+
+    def resume_concatunicode(self, v_pos, leftpos, rightpos):
+        xxx
+
     def resume_new_with_vtable(self, v_pos, c_const_class):
         self.l.append("%d = resume_new_with_vtable %d" % (v_pos,
                                                 c_const_class.getint()))
diff --git a/rpython/jit/resume/rescode.py b/rpython/jit/resume/rescode.py
--- a/rpython/jit/resume/rescode.py
+++ b/rpython/jit/resume/rescode.py
@@ -4,7 +4,8 @@
 
 (UNUSED, ENTER_FRAME, LEAVE_FRAME, RESUME_PUT,
  RESUME_NEW, RESUME_NEW_WITH_VTABLE, RESUME_SETFIELD_GC,
- RESUME_SET_PC, RESUME_CLEAR) = range(9)
+ RESUME_SET_PC, RESUME_CLEAR, RESUME_NEWSTR, RESUME_NEWUNICODE,
+ RESUME_CONCATSTR, RESUME_CONCATUNICODE) = range(13)
 
 TAGCONST = 0x0
 TAGVIRTUAL = 0x2
@@ -88,6 +89,17 @@
         self.write_short(v_pos) # XXX byte virtuals?
         self.write_short(descr.global_descr_index)
 
+    def resume_newunicode(self, v_pos, lgt):
+        self.write(RESUME_NEWUNICODE)
+        self.write_short(v_pos) # XXX byte virtuals?
+        self.write(lgt)
+
+    def resume_concatunicode(self, v_pos, leftpos, rightpos):
+        self.write(RESUME_CONCATUNICODE)
+        self.write_short(v_pos)
+        self.write_short(leftpos)
+        self.write_short(rightpos)
+
     def resume_new_with_vtable(self, v_pos, const_class):
         self.write(RESUME_NEW_WITH_VTABLE)
         self.write_short(v_pos) # XXX byte virtuals?
diff --git a/rpython/jit/resume/test/test_frontend.py b/rpython/jit/resume/test/test_frontend.py
--- a/rpython/jit/resume/test/test_frontend.py
+++ b/rpython/jit/resume/test/test_frontend.py
@@ -2,7 +2,7 @@
 from rpython.jit.tool.oparser import parse
 from rpython.jit.codewriter.jitcode import JitCode
 from rpython.jit.metainterp.history import AbstractDescr, Const, INT, Stats,\
-     ConstInt, REF
+     ConstInt, REF, FLOAT
 from rpython.jit.resume.frontend import rebuild_from_resumedata,\
      blackhole_from_resumedata
 from rpython.jit.resume.rescode import ResumeBytecode, TAGBOX,\
@@ -30,6 +30,9 @@
     def is_field_signed(self):
         return self.kind == INT
 
+    def is_float_field(self):
+        return self.kind == FLOAT
+
 class MockLoop(object):
     pass
 
@@ -251,12 +254,12 @@
         rebuild_from_resumedata(metainterp, "myframe", descr)
         expected = [(rop.NEW, descr),
                     (rop.SETFIELD_GC, d2, AnyBox(), EqConstInt(1)),
-                    (rop.NEW_WITH_VTABLE, EqConstInt(cls_as_int)),
+                    (rop.NEW_WITH_VTABLE, None, EqConstInt(cls_as_int)),
                     (rop.SETFIELD_GC, d3, AnyBox(), AnyBox()),
                     (rop.RESUME_PUT, None, AnyBox(), EqConstInt(0),
                      EqConstInt(0))]
         expected2 = [(rop.NEW, descr),
-                     (rop.NEW_WITH_VTABLE, EqConstInt(cls_as_int)),
+                     (rop.NEW_WITH_VTABLE, None, EqConstInt(cls_as_int)),
                      (rop.SETFIELD_GC, d3, AnyBox(), AnyBox()),
                      (rop.SETFIELD_GC, d2, AnyBox(), EqConstInt(1)),
                      (rop.RESUME_PUT, None, AnyBox(), EqConstInt(0),


More information about the pypy-commit mailing list