[pypy-commit] pypy value-classes: Attempted support for unpacking constant pointers

sbauman pypy.commits at gmail.com
Thu Sep 29 17:05:09 EDT 2016


Author: Spenser Bauman <sabauma at gmail.com>
Branch: value-classes
Changeset: r87456:48e89a5c1a07
Date: 2016-09-29 17:04 -0400
http://bitbucket.org/pypy/pypy/changeset/48e89a5c1a07/

Log:	Attempted support for unpacking constant pointers

diff --git a/rpython/jit/metainterp/optimizeopt/unroll.py b/rpython/jit/metainterp/optimizeopt/unroll.py
--- a/rpython/jit/metainterp/optimizeopt/unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/unroll.py
@@ -328,7 +328,8 @@
                         guard.rd_resume_position = patchguardop.rd_resume_position
                         guard.setdescr(compile.ResumeAtPositionDescr())
                     self.send_extra_operation(guard)
-            except VirtualStatesCantMatch:
+            except VirtualStatesCantMatch as e:
+                print "*** failing with: ", e.msg
                 continue
 
             # When force_boxes == True, creating the virtual args can fail when
@@ -337,8 +338,9 @@
             try:
                 args, virtuals = target_virtual_state.make_inputargs_and_virtuals(
                     args, self.optimizer, force_boxes=force_boxes)
-            except VirtualStatesCantMatch:
+            except VirtualStatesCantMatch as e:
                 assert force_boxes
+                print "*** failing with: ", e.msg
                 virtual_state = self.get_virtual_state(args)
                 continue
 
diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py b/rpython/jit/metainterp/optimizeopt/virtualstate.py
--- a/rpython/jit/metainterp/optimizeopt/virtualstate.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py
@@ -219,7 +219,7 @@
     @specialize.argtype(4)
     def getfield(self, box, info, descr, optimizer):
         assert isinstance(info, AbstractStructPtrInfo)
-        field = info._fields[descr.get_index()]
+        field = info.getfield(descr, optimizer)
         if field is not None:
             return field
         opnum = rop.getfield_for_descr(descr)
@@ -229,12 +229,18 @@
         else:
             from rpython.jit.metainterp.optimizeopt import Optimizer
             assert isinstance(optimizer, Optimizer)
-            optimizer.emit_operation(getfield)
-        info._fields[descr.get_index()] = getfield
+            optimizer.send_extra_operation(getfield)
+        info.setfield(descr, None, getfield)
         return getfield
 
     def make_virtual_copy(self, box, info, optimizer):
         optvirtualize = optimizer.optvirtualize
+
+        if isinstance(box, ConstPtr):
+            # Wrap const pointers in SAME_AS_R operation to cloning via
+            # make_virtual, which expects a ResOperation with an opnum.
+            box = ResOperation(rop.SAME_AS_R, [box])
+
         opinfo = optvirtualize.make_virtual(self.known_class, box, self.typedescr)
         for i in range(len(info._fields)):
             descr = self.fielddescrs[i]
@@ -250,6 +256,9 @@
             return AbstractVirtualStructStateInfo.enum_forced_boxes(
                     self, boxes, box, optimizer, force_boxes)
 
+        if isinstance(info, ConstPtrInfo):
+            optheap = optimizer.optimizer.optheap
+            info = info._get_info(self.typedescr, optheap)
         assert isinstance(info, AbstractStructPtrInfo)
 
         # TODO: Do we need to create a new object via NEW_WITH_VTABLE, or will the
@@ -273,7 +282,7 @@
         assert isinstance(other, NotVirtualStateInfoPtr)
 
         if not self.typedescr.is_value_class():
-            raise VirtualStatesCantMatch("different kinds of structs")
+            raise VirtualStatesCantMatch("_generate_guards_non_virtual: different kinds of structs")
 
         # raise VirtualStatesCantMatch("different kinds of structs")
         # TODO: Probably should rename state.extra_guards to extra_ops
@@ -290,7 +299,7 @@
             extra_guards.append(op)
         elif other.level == LEVEL_KNOWNCLASS:
             if not self.known_class.same_constant(other.known_class):
-                raise VirtualStatesCantMatch("classes don't match")
+                raise VirtualStatesCantMatch("_generate_guards_non_virtual: classes don't match")
         else:
             assert other.level == LEVEL_CONSTANT
             known = self.known_class
@@ -298,7 +307,7 @@
             if const.nonnull() and known.same_constant(cpu.ts.cls_of_box(const)):
                 pass
             else:
-                raise VirtualStatesCantMatch("classes don't match")
+                raise VirtualStatesCantMatch("_generate_guards_non_virtual: classes don't match")
 
         # Things to do...
         # 1. Generate new_with_vtable operation to allocate the new virtual object
@@ -308,11 +317,13 @@
         #     non-virtual object which we are promoting to a virtual. How do we
         #     generate this new virtual state so we can operate recursively)
 
+        optimizer = state.optimizer
         if runtime_box is not None:
-            opinfo = state.optimizer.getptrinfo(box)
-            if opinfo is not None and not isinstance(opinfo, AbstractStructPtrInfo):
-                assert isinstance(opinfo, ConstPtrInfo)
-                raise VirtualStatesCantMatch("cannot yet handle const pointers")
+            opinfo = optimizer.getptrinfo(box)
+            if isinstance(opinfo, ConstPtrInfo):
+                optheap = optimizer.optheap
+                opinfo = opinfo._get_info(self.typedescr, optheap)
+            assert opinfo is None or isinstance(opinfo, AbstractStructPtrInfo)
         else:
             opinfo = None
 
diff --git a/rpython/jit/metainterp/test/test_virtual.py b/rpython/jit/metainterp/test/test_virtual.py
--- a/rpython/jit/metainterp/test/test_virtual.py
+++ b/rpython/jit/metainterp/test/test_virtual.py
@@ -1087,33 +1087,39 @@
         self.meta_interp(f, [])
 
     def test_avoid_preamble_4(self):
-        driver = JitDriver(greens=[], reds=['i', 'val'])
+        driver = JitDriver(greens=[], reds=['i', 'acc', 'val'])
         class X(object):
             _value_class_ = True
             def __init__(self, v):
                 self.v = v
 
         const = X(5)
+        arr = [None]
         def f():
             # Prevent all retracing of side exits. Ensures that the unroll
             # optimizer will attempt to jump to either the preamble or loop.
             set_param(driver, 'retrace_limit', -1)
             set_param(driver, 'threshold', 1)
-            val   = X(0)
-            i     = 0
+            val = X(0)
+            acc = 0
+            i = 0
             while i < 17:
-                driver.can_enter_jit(i=i, val=val)
-                driver.jit_merge_point(i=i, val=val)
+                driver.can_enter_jit(i=i, acc=acc, val=val)
+                driver.jit_merge_point(i=i, acc=acc, val=val)
                 # Logical & rather than comparison to confuse range analysis.
                 # Test only succeeds on the first 2 iterations
+                arr[0] = val
                 if i & -2 == 0:
                     val = X(i)
                 else:
                     val = const
+                acc += val.v
                 i += 1
             return 0
 
         self.meta_interp(f, [])
+        loop = get_stats().loops[0]
+        import pdb; pdb.set_trace()
 
     def test_aliased_virtual_states(self):
         # All cases are covered when forcing one component of the virtual state
@@ -1150,6 +1156,30 @@
         self.meta_interp(f, [])
         # assert did not crash
 
+    def test_double_allocation(self):
+        driver = JitDriver(greens=[], reds=['i'])
+
+        class X(object):
+            _value_class_ = True
+            def __init__(self, v):
+                self.v = v
+
+        array = [None, None]
+        def f():
+            # Prevent all retracing of side exits. Ensures that the unroll
+            # optimizer will attempt to jump to either the preamble or loop.
+            set_param(driver, 'retrace_limit', -1)
+            set_param(driver, 'threshold', 1)
+            i = 0
+            while i < 17:
+                driver.can_enter_jit(i=i)
+                driver.jit_merge_point(i=i)
+                array[0] = X(i)
+                array[1] = X(i)
+                i += 1
+            return 0
+
+        self.meta_interp(f, [])
 
 class VirtualMiscTests:
     def test_multiple_equal_virtuals(self):


More information about the pypy-commit mailing list