[pypy-commit] pypy optresult: start whacking at vstring

fijal noreply at buildbot.pypy.org
Tue May 26 19:20:48 CEST 2015


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: optresult
Changeset: r77590:2b9aa1b850b7
Date: 2015-05-26 19:20 +0200
http://bitbucket.org/pypy/pypy/changeset/2b9aa1b850b7/

Log:	start whacking at vstring

diff --git a/rpython/jit/metainterp/optimizeopt/info.py b/rpython/jit/metainterp/optimizeopt/info.py
--- a/rpython/jit/metainterp/optimizeopt/info.py
+++ b/rpython/jit/metainterp/optimizeopt/info.py
@@ -172,25 +172,6 @@
         assert self.is_virtual()
         return visitor.visit_vstruct(self.vdescr, fielddescrs)
 
-class StrPtrInfo(AbstractVirtualPtrInfo):
-    _attrs_ = ('length', 'lenbound')
-
-    length = -1
-    lenbound = None
-    
-    def __init__(self):
-        pass
-
-    def getlenbound(self):
-        from rpython.jit.metainterp.optimizeopt import intutils
-
-        if self.lenbound is None:
-            if self.length == -1:
-                self.lenbound = intutils.IntBound(0, intutils.MAXINT)
-            else:
-                self.lenbound = intutils.ConstIntBound(self.length)
-        return self.lenbound
-
 class ArrayPtrInfo(AbstractVirtualPtrInfo):
     _attrs_ = ('length', '_items', 'lenbound', '_clear')
 
diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py
--- a/rpython/jit/metainterp/optimizeopt/intbounds.py
+++ b/rpython/jit/metainterp/optimizeopt/intbounds.py
@@ -392,9 +392,9 @@
 
     def optimize_STRGETITEM(self, op):
         self.emit_operation(op)
-        v1 = self.getvalue(op)
-        v1.getintbound().make_ge(IntLowerBound(0))
-        v1.getintbound().make_lt(IntUpperBound(256))
+        v1 = self.getintbound(op)
+        v1.make_ge(IntLowerBound(0))
+        v1.make_lt(IntUpperBound(256))
 
     def optimize_GETFIELD_RAW_I(self, op):
         self.emit_operation(op)
@@ -428,8 +428,8 @@
 
     def optimize_UNICODEGETITEM(self, op):
         self.emit_operation(op)
-        v1 = self.getvalue(op)
-        v1.getintbound().make_ge(IntLowerBound(0))
+        b1 = self.getintbound(op)
+        b1.make_ge(IntLowerBound(0))
 
     def make_int_lt(self, box1, box2):
         b1 = self.getintbound(box1)
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -360,6 +360,9 @@
     def make_nonnull(self, op):
         return self.optimizer.make_nonnull(op)
 
+    def make_nonnull_str(self, op, mode):
+        return self.optimizer.make_nonnull_str(op, mode)
+
     def get_constant_box(self, box):
         return self.optimizer.get_constant_box(box)
 
@@ -548,6 +551,9 @@
         box = self.get_box_replacement(box)
         if isinstance(box, Const):
             return box
+        if (box.type == 'i' and box.get_forwarded() and
+            box.get_forwarded().is_constant()):
+            return ConstInt(box.get_forwarded().getint())
         #self.ensure_imported(value)
 
     def get_newoperations(self):
@@ -600,7 +606,20 @@
             return
         op.set_forwarded(info.NonNullPtrInfo())
 
+    def make_nonnull_str(self, op, mode):
+        from rpython.jit.metainterp.optimizeopt import vstring
+        
+        op = self.get_box_replacement(op)
+        if op.is_constant():
+            return
+        opinfo = op.get_forwarded()
+        if isinstance(opinfo, vstring.StrPtrInfo):
+            return
+        op.set_forwarded(vstring.StrPtrInfo(mode))
+
     def ensure_ptr_info_arg0(self, op):
+        from rpython.jit.metainterp.optimizeopt import vstring
+        
         arg0 = self.get_box_replacement(op.getarg(0))
         if arg0.is_constant():
             return info.ConstPtrInfo(arg0)
@@ -623,8 +642,10 @@
             opinfo = info.ArrayPtrInfo(op.getdescr())
         elif op.getopnum() == rop.GUARD_CLASS:
             opinfo = info.InstancePtrInfo()
-        elif op.getopnum() in (rop.STRLEN, rop.UNICODELEN):
-            opinfo = info.StrPtrInfo()
+        elif op.getopnum() in (rop.STRLEN,):
+            opinfo = vstring.StrPtrInfo(vstring.mode_string)            
+        elif op.getopnum() in (rop.UNICODELEN,):
+            opinfo = vstring.StrPtrInfo(vstring.mode_unicode)
         else:
             xxx
         opinfo.last_guard_pos = last_guard_pos
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
@@ -6,6 +6,7 @@
 from rpython.jit.metainterp.optimizeopt.optimizer import llhelper, REMOVED
 from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from rpython.jit.metainterp.resoperation import rop, ResOperation, DONT_CHANGE
+from rpython.jit.metainterp.optimizeopt import info
 from rpython.rlib.objectmodel import specialize, we_are_translated
 from rpython.rlib.unroll import unrolling_iterable
 from rpython.rtyper import annlowlevel
@@ -45,6 +46,160 @@
 # ____________________________________________________________
 
 
+
+class StrPtrInfo(info.NonNullPtrInfo):
+    _attrs_ = ('length', 'lenbound', 'lgtop', 'mode')
+
+    lenbound = None
+    lgtop = None
+
+    def __init__(self, mode, is_virtual=False, length=-1):
+        self.length = length
+        self._is_virtual = is_virtual
+        self.mode = mode
+
+    def getlenbound(self):
+        from rpython.jit.metainterp.optimizeopt import intutils
+
+        if self.lenbound is None:
+            if self.length == -1:
+                self.lenbound = intutils.IntBound(0, intutils.MAXINT)
+            else:
+                self.lenbound = intutils.ConstIntBound(self.length)
+        return self.lenbound
+
+    def get_constant_string_spec(self, mode):
+        if self.is_constant():
+            xxx
+        return None
+
+    def force_box(self, op, optforce):
+        if not self.is_virtual():
+            return op
+        self._is_virtual = False
+        if self.mode is mode_string:
+            s = self.get_constant_string_spec(mode_string)
+            if s is not None:
+                c_s = get_const_ptr_for_string(s)
+                self.make_constant(c_s)
+                return
+        else:
+            s = self.get_constant_string_spec(mode_unicode)
+            if s is not None:
+                c_s = get_const_ptr_for_unicode(s)
+                self.make_constant(c_s)
+                return
+        lengthbox = self.getstrlen(op, optforce, self.mode, None)
+        newop = ResOperation(self.mode.NEWSTR, [lengthbox])
+        if not we_are_translated():
+            newop.name = 'FORCE'
+        optforce.emit_operation(newop)
+        newop = optforce.getlastop()
+        newop.set_forwarded(self)
+        op = optforce.get_box_replacement(op)
+        op.set_forwarded(newop)
+        self.initialize_forced_string(op, optforce, op, CONST_0, self.mode)
+
+    def initialize_forced_string(self, op, string_optimizer, targetbox,
+                                 offsetbox, mode):
+        return self.string_copy_parts(op, string_optimizer, targetbox,
+                                      offsetbox, mode)
+
+    def getstrlen(self, op, string_optimizer, mode, lengthop):
+        if self.lgtop is not None:
+            return self.lgtop
+        if mode is mode_string:
+            s = self.get_constant_string_spec(mode_string)
+            if s is not None:
+                return ConstInt(len(s))
+        else:
+            s = self.get_constant_string_spec(mode_unicode)
+            if s is not None:
+                return ConstInt(len(s))
+        if string_optimizer is None:
+            return None
+        assert not self.is_virtual()
+        if lengthop is not None:
+            xxx
+            box = self.force_box(op, string_optimizer)
+            lengthop = string_optimizer.optimizer.replace_op_with(lengthop,
+                mode.STRLEN, [box])
+        else:
+            lengthop = ResOperation(mode.STRLEN, [op])
+        self.lgtop = lengthop
+        string_optimizer.emit_operation(lengthop)
+        return lengthop
+
+    def string_copy_parts(self, op, string_optimizer, targetbox, offsetbox,
+                          mode):
+         # Copies the pointer-to-string 'self' into the target string
+         # given by 'targetbox', at the specified offset.  Returns the offset
+         # at the end of the copy.
+         lengthbox = self.getstrlen(op, string_optimizer, mode, None)
+         srcbox = self.force_box(op, string_optimizer)
+         return copy_str_content(string_optimizer, srcbox, targetbox,
+                                 CONST_0, offsetbox, lengthbox, mode)
+
+class VStringPlainInfo(StrPtrInfo):
+    _attrs_ = ('mode', '_is_virtual')
+    
+    def __init__(self, mode, is_virtual, length):
+        if is_virtual:
+            assert length != -1
+            self._chars = [None] * length
+        StrPtrInfo.__init__(self, mode, is_virtual, length)
+
+    def setitem(self, index, item):
+        self._chars[index] = item
+
+    def getitem(self, index):
+        return self._chars[index]
+
+    def is_virtual(self):
+        return self._is_virtual
+
+    def getstrlen(self, op, string_optimizer, mode, lengthop):
+        xxx
+
+class VStringSliceInfo(StrPtrInfo):
+    pass
+
+class VStringConcatInfo(StrPtrInfo):
+    _attrs_ = ('mode', 'vleft', 'vright', '_is_virtual')
+    
+    def __init__(self, mode, vleft, vright, is_virtual):
+        self.vleft = vleft
+        self.vright = vright
+        StrPtrInfo.__init__(self, mode, is_virtual)
+
+    def is_virtual(self):
+        return self._is_virtual
+
+    def getstrlen(self, op, string_optimizer, mode, ignored):
+        if self.lgtop is not None:
+            return self.lgtop
+        lefti = string_optimizer.getptrinfo(self.vleft)
+        len1box = lefti.getstrlen(self.vleft, string_optimizer, mode, None)
+        if len1box is None:
+            return None
+        righti = string_optimizer.getptrinfo(self.vright)
+        len2box = righti.getstrlen(self.vright, string_optimizer, mode, None)
+        if len2box is None:
+            return None
+        self.lgtop = _int_add(string_optimizer, len1box, len2box)
+            # ^^^ may still be None, if string_optimizer is None
+        return self.lgtop
+
+    def string_copy_parts(self, op, string_optimizer, targetbox, offsetbox,
+                          mode):
+        lefti = string_optimizer.getptrinfo(self.vleft)
+        offsetbox = lefti.string_copy_parts(self.vleft, string_optimizer,
+                                            targetbox, offsetbox, mode)
+        righti = string_optimizer.getptrinfo(self.vright)
+        offsetbox = righti.string_copy_parts(self.vright, string_optimizer,
+                                             targetbox, offsetbox, mode)
+        return offsetbox
+
 # class __extend__(optimizer.OptValue):
 #     """New methods added to the base class OptValue for this file."""
 
@@ -122,7 +277,7 @@
                                       offsetbox, mode)
 
 
-class VStringPlainInfo(VAbstractStringInfo):
+class XVStringPlainInfo(VAbstractStringInfo):
     """A string built with newstr(const)."""
     _lengthbox = None     # cache only
 
@@ -216,7 +371,7 @@
         return visitor.visit_vstrplain(self.mode is mode_unicode)
 
 
-class VStringConcatInfo(VAbstractStringInfo):
+class XVStringConcatInfo(VAbstractStringInfo):
     """The concatenation of two other strings."""
     _attrs_ = ('left', 'right', 'lengthbox')
 
@@ -269,7 +424,7 @@
         return visitor.visit_vstrconcat(self.mode is mode_unicode)
 
 
-class VStringSliceInfo(VAbstractStringInfo):
+class XVStringSliceInfo(VAbstractStringInfo):
     """A slice."""
     _attrs_ = ('vstr', 'vstart', 'vlength')
 
@@ -356,7 +511,7 @@
     if string_optimizer is None:
         return None
     op = ResOperation(rop.INT_ADD, [box1, box2])
-    string_optimizer.emit_operation(op)
+    string_optimizer.send_extra_operation(op)
     return op
 
 def _int_sub(string_optimizer, box1, box2):
@@ -366,7 +521,7 @@
         if isinstance(box1, ConstInt):
             return ConstInt(box1.value - box2.value)
     op = ResOperation(rop.INT_SUB, [box1, box2])
-    string_optimizer.emit_operation(op)
+    string_optimizer.send_extra_operation(op)
     return op
 
 def _strgetitem(string_optimizer, strbox, indexbox, mode, resbox=None):
@@ -389,14 +544,14 @@
 class OptString(optimizer.Optimization):
     "Handling of strings and unicodes."
 
-    def make_vstring_plain(self, source_op, mode):
-        vvalue = VStringPlainValue(source_op, mode)
-        self.make_equal_to(source_op, vvalue)
+    def make_vstring_plain(self, op, mode, length):
+        vvalue = VStringPlainInfo(mode, True, length)
+        self.make_equal_to(op, vvalue)
         return vvalue
 
-    def make_vstring_concat(self, source_op, mode):
-        vvalue = VStringConcatValue(source_op, mode)
-        self.make_equal_to(source_op, vvalue)
+    def make_vstring_concat(self, op, mode, vleft, vright):
+        vvalue = VStringConcatInfo(mode, vleft, vright, True)
+        self.make_equal_to(op, vvalue)
         return vvalue
 
     def make_vstring_slice(self, source_op, mode):
@@ -419,8 +574,7 @@
                 op = op.copy_and_change(mode.NEWSTR, [length_box])
             else:
                 old_op = None
-            vvalue = self.make_vstring_plain(op, mode)
-            vvalue.setup(length_box.getint())
+            vvalue = self.make_vstring_plain(op, mode, length_box.getint())
             if old_op is not None:
                 self.optimizer.make_equal_to(old_op, vvalue)
         else:
@@ -429,14 +583,15 @@
             self.pure(mode.STRLEN, [op], op.getarg(0))
 
     def optimize_STRSETITEM(self, op):
-        value = self.getvalue(op.getarg(0))
+        value = self.getptrinfo(op.getarg(0))
         assert not value.is_constant() # strsetitem(ConstPtr) never makes sense
-        if value.is_virtual() and isinstance(value, VStringPlainValue):
+        if value and value.is_virtual():
             indexbox = self.get_constant_box(op.getarg(1))
             if indexbox is not None:
-                value.setitem(indexbox.getint(), self.getvalue(op.getarg(2)))
+                value.setitem(indexbox.getint(),
+                              self.get_box_replacement(op.getarg(2)))
                 return
-        value.ensure_nonnull()
+        self.make_nonnull(op.getarg(0))
         self.emit_operation(op)
 
     optimize_UNICODESETITEM = optimize_STRSETITEM
@@ -447,27 +602,27 @@
         self._optimize_STRGETITEM(op, mode_unicode)
 
     def _optimize_STRGETITEM(self, op, mode):
-        value = self.getvalue(op.getarg(0))
-        vindex = self.getvalue(op.getarg(1))
-        vresult = self.strgetitem(value, vindex, mode, op)
-        if op in self.optimizer.values:
-            assert self.getvalue(op) is vresult
-        else:
-            self.make_equal_to(op, vresult)
+        strinfo = self.getptrinfo(op.getarg(0))
+        vindex = self.getintbound(op.getarg(1))
+        res = self.strgetitem(op, strinfo, vindex, mode, op)
+        if res is not None:
+            self.make_equal_to(op, res)
 
-    def strgetitem(self, value, vindex, mode, resbox=None):
-        value.ensure_nonnull()
+    def strgetitem(self, op, sinfo, vindex, mode, resbox=None):
+        self.make_nonnull(op.getarg(0))
         #
-        if value.is_virtual() and isinstance(value, VStringSliceValue):
+        if isinstance(sinfo, VStringSliceInfo) and sinfo.is_virtual(): # slice
+            xxx
             fullindexbox = _int_add(self,
                                     value.vstart.force_box(self),
                                     vindex.force_box(self))
             value = value.vstr
             vindex = self.getvalue(fullindexbox)
         #
-        if isinstance(value, VStringPlainValue):  # even if no longer virtual
+        if isinstance(sinfo, VStringPlainInfo):
+            # even if no longer virtual
             if vindex.is_constant():
-                result = value.getitem(vindex.box.getint())
+                result = sinfo.getitem(vindex.getint())
                 if result is not None:
                     return result
         #
@@ -482,6 +637,7 @@
                     vindex = optimizer.ConstantIntValue(ConstInt(index - len1))
                     return self.strgetitem(value.right, vindex, mode)
         #
+        xxx
         resbox = _strgetitem(self, value.force_box(self), vindex.force_box(self), mode, resbox)
         return self.getvalue(resbox)
 
@@ -604,12 +760,11 @@
         return True
 
     def opt_call_stroruni_STR_CONCAT(self, op, mode):
-        vleft = self.getvalue(op.getarg(1))
-        vright = self.getvalue(op.getarg(2))
-        vleft.ensure_nonnull()
-        vright.ensure_nonnull()
-        value = self.make_vstring_concat(op, mode)
-        value.setup(vleft, vright)
+        self.make_nonnull_str(op.getarg(1), mode)
+        self.make_nonnull_str(op.getarg(2), mode)
+        self.make_vstring_concat(op, mode,
+                                 self.get_box_replacement(op.getarg(1)),
+                                 self.get_box_replacement(op.getarg(2)))
         return True
 
     def opt_call_stroruni_STR_SLICE(self, op, mode):


More information about the pypy-commit mailing list