Author: Antonio Cuni <[email protected]>
Branch: faster-rstruct
Changeset: r80762:4fb804c3e5fe
Date: 2015-11-18 17:33 +0100
http://bitbucket.org/pypy/pypy/changeset/4fb804c3e5fe/

Log:    fix the optimizer, which gets confused when we pass a virtual string
        to getarrayitem_gc

diff --git a/rpython/jit/metainterp/optimizeopt/heap.py 
b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -535,10 +535,14 @@
         cf.do_setfield(self, op)
 
     def optimize_GETARRAYITEM_GC_I(self, op):
+        # When using str_storage_getitem we op.getarg(0) is a string, NOT an
+        # array. That's why we need to check for .is_array() before
+        # remembering the reads. There is no point in remembering it, as the
+        # box will be forced anyway by the optimizer
         arrayinfo = self.ensure_ptr_info_arg0(op)
         indexb = self.getintbound(op.getarg(1))
         cf = None
-        if indexb.is_constant():
+        if indexb.is_constant() and arrayinfo.is_array():
             index = indexb.getint()
             arrayinfo.getlenbound(None).make_gt_const(index)
             # use the cache on (arraydescr, index), which is a constant
@@ -555,7 +559,7 @@
         self.make_nonnull(op.getarg(0))
         self.emit_operation(op)
         # the remember the result of reading the array item
-        if cf is not None:
+        if cf is not None and arrayinfo.is_array():
             arrayinfo.setitem(op.getdescr(), indexb.getint(),
                               self.get_box_replacement(op.getarg(0)),
                               self.get_box_replacement(op), cf,
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
@@ -49,6 +49,9 @@
     def is_null(self):
         return False
 
+    def is_array(self):
+        return False
+
     def force_at_the_end_of_preamble(self, op, optforce, rec):
         if not self.is_virtual():
             return optforce.get_box_replacement(op)
@@ -478,6 +481,9 @@
             self.lenbound = intutils.ConstIntBound(size)
         self._clear = clear
 
+    def is_array(self):
+        return True
+
     def getlenbound(self, mode):
         from rpython.jit.metainterp.optimizeopt import intutils
 
@@ -716,6 +722,9 @@
     def is_virtual(self):
         return False
 
+    def is_array(self):
+        return True
+
     def get_known_class(self, cpu):
         if not self._const.nonnull():
             return None
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
@@ -271,8 +271,11 @@
             self.emit_operation(op)
 
     def optimize_GETARRAYITEM_GC_I(self, op):
+        # When using str_storage_getitem we op.getarg(0) is a string, NOT an
+        # array, hence the check for is_array(). If it's a virtual but not an
+        # array (i.e., if it's a string) it will be forced.
         opinfo = self.getptrinfo(op.getarg(0))
-        if opinfo and opinfo.is_virtual():
+        if opinfo and opinfo.is_virtual() and opinfo.is_array():
             indexbox = self.get_constant_box(op.getarg(1))
             if indexbox is not None:
                 item = opinfo.getitem(op.getdescr(), indexbox.getint())
diff --git a/rpython/jit/metainterp/test/test_strstorage.py 
b/rpython/jit/metainterp/test/test_strstorage.py
--- a/rpython/jit/metainterp/test/test_strstorage.py
+++ b/rpython/jit/metainterp/test/test_strstorage.py
@@ -1,5 +1,6 @@
 import py
-from rpython.rtyper.lltypesystem import lltype
+import struct
+from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rlib.strstorage import str_storage_getitem
 from rpython.rlib.test.test_strstorage import BaseStrStorageTest
 from rpython.jit.codewriter import longlong
@@ -26,3 +27,20 @@
             # back!
             return longlong.int2singlefloat(res)
         return res
+
+
+    def test_force_virtual_str_storage(self):
+        size = rffi.sizeof(lltype.Signed)
+        def f(val):
+            x = chr(val) + '\x00'*(size-1)
+            return str_storage_getitem(lltype.Signed, x, 0)
+        res = self.interp_operations(f, [42], supports_singlefloats=True)
+        assert res == 42
+        self.check_operations_history({
+            'newstr': 1,              # str forcing
+            'strsetitem': 1,          # str forcing
+            'call_pure_r': 1,         # str forcing (copystrcontent)
+            'guard_no_exception': 1,  # str forcing
+            'getarrayitem_gc_i': 1,   # str_storage_getitem
+            'finish': 1
+            })
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to