Author: Carl Friedrich Bolz <cfb...@gmx.de>
Branch: guard-compatible
Changeset: r85358:9f336d3981bb
Date: 2016-06-23 11:41 +0200
http://bitbucket.org/pypy/pypy/changeset/9f336d3981bb/

Log:    intermediate checkin: start sketching guard_compatible support in
        virtualstate

diff --git a/rpython/jit/metainterp/compatible.py 
b/rpython/jit/metainterp/compatible.py
--- a/rpython/jit/metainterp/compatible.py
+++ b/rpython/jit/metainterp/compatible.py
@@ -42,12 +42,17 @@
         res.frozen = True
         return res
 
-    def record_condition(self, cond, res, optimizer):
+    def contains_condition(self, cond, res=None):
         for oldcond in self.conditions:
             if oldcond.same_cond(cond, res):
                 return True
+        return False
+
+    def record_condition(self, cond, res, optimizer):
+        if self.contains_condition(cond, res):
+            return True
         if self.frozen:
-            False
+            return False
         cond.activate(res, optimizer)
         if self.conditions and self.conditions[-1].debug_mp_str == 
cond.debug_mp_str:
             cond.debug_mp_str = ''
@@ -57,11 +62,17 @@
     def register_quasi_immut_field(self, op):
         self.last_quasi_immut_field_op = op
 
-    def check_compat_and_activate(self, cpu, ref, loop_token):
+    def check_compat(self, cpu, ref):
         for cond in self.conditions:
             if not cond.check(cpu, ref):
                 return False
-        # need to tell all conditions, in case a quasi-immut needs to be 
registered
+        return True
+
+    def check_compat_and_activate(self, cpu, ref, loop_token):
+        if not self.check_compat(cpu, ref):
+            return False
+        # need to tell all conditions, in case a quasi-immut needs to be
+        # registered
         for cond in self.conditions:
             cond.activate_secondary(ref, loop_token)
         return True
@@ -123,6 +134,23 @@
         for cond in self.conditions:
             cond.emit_condition(op, short, optimizer)
 
+    def emit_needed_conditions_if_const_matches(
+            self, other, const, op, extra_guards, optimizer, cpu):
+        """ go through self.conditions. if the condition is present in other,
+        do nothing. If it is not, check whether ref matches the condition. If
+        not return False, otherwise emit guards for the condition. Return True
+        at the end. """
+        for cond in self.conditions:
+            if other is None or not other.contains_condition(cond):
+                if const is None:
+                    return False
+                ref = const.getref_base()
+                if cond.check(cpu, ref):
+                    cond.emit_condition(op, short, optimizer)
+                else:
+                    return False
+        return True
+
     def repr_of_conditions(self, argrepr="?"):
         return "\n".join([cond.repr(argrepr) for cond in self.conditions])
 
@@ -151,7 +179,7 @@
     def activate_secondary(self, ref, loop_token):
         pass
 
-    def same_cond(self, other, res):
+    def same_cond(self, other, res=None):
         return False
 
     def repr(self):
@@ -216,11 +244,13 @@
             return False
         return True
 
-    def same_cond(self, other, res):
+    def same_cond(self, other, res=None):
         if type(other) is not PureCallCondition:
             return False
         if len(self.args) != len(other.args):
             return False
+        if res is None:
+            res = other.res
         if not self.res.same_constant(res):
             return False
         if self.descr is not other.descr:
@@ -321,11 +351,13 @@
             return False
         return True
 
-    def same_cond(self, other, res):
+    def same_cond(self, other, res=None):
         if type(other) is not QuasiimmutGetfieldAndPureCallCondition:
             return False
         if len(self.args) != len(other.args):
             return False
+        if res is None:
+            res = other.res
         if not self.res.same_constant(res):
             return False
         if self.descr is not other.descr:
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
@@ -355,6 +355,8 @@
     if type == 'i':
         return NotVirtualStateInfoInt(cpu, type, info)
     if type == 'r':
+        if info._compatibility_conditions is not None:
+            return NotVirtualStateInfoPtrCompatible(cpu, type, info)
         return NotVirtualStateInfoPtr(cpu, type, info)
     return NotVirtualStateInfo(cpu, type, info)
 
@@ -597,6 +599,29 @@
             else:
                 raise VirtualStatesCantMatch("classes don't match")
 
+class NotVirtualStateInfoPtrCompatible(NotVirtualStateInfoPtr):
+    def __init__(self, cpu, type, info):
+        ccond = info._compatibility_conditions
+        self._compatibility_conditions = ccond.frozen_copy()
+        NotVirtualStateInfoPtr.__init__(self, cpu, type, info)
+
+    def _generate_guards(self, other, box, runtime_box, state):
+        NotVirtualStateInfoPtr._generate_guards(
+            self, other, box, runtime_box, state)
+        ccond_self = self._compatibility_conditions
+        if isinstance(other, NotVirtualStateInfoPtrCompatible):
+            ccond_other = other._compatibility_conditions
+        else:
+            ccond_other = None
+        const = None
+        if runtime_box is not None:
+            const = runtime_box.constbox()
+        if ccond_self.emit_needed_conditions_if_const_matches(
+                ccond_other, const, box, state.extra_guards,
+                state.optimizer, state.cpu):
+            return
+        raise VirtualStatesCantMatch("target compatibility conditions aren't 
met")
+
 
 class VirtualState(object):
     def __init__(self, state):
diff --git a/rpython/jit/metainterp/test/test_compatible.py 
b/rpython/jit/metainterp/test/test_compatible.py
--- a/rpython/jit/metainterp/test/test_compatible.py
+++ b/rpython/jit/metainterp/test/test_compatible.py
@@ -42,8 +42,8 @@
         x = self.meta_interp(main, [])
 
         assert x < 30
-        # trace, two bridges, a finish bridge
-        self.check_trace_count(4)
+        # trace, one bridge, a finish bridge
+        self.check_trace_count(3)
 
     def test_simple_check_values(self):
         S = lltype.GcStruct('S', ('x', lltype.Signed))
@@ -87,8 +87,8 @@
         x = self.meta_interp(main, [])
 
         assert x == main()
-        # trace, two bridges, a finish bridge
-        self.check_trace_count(4)
+        # trace, a bridge, a finish bridge
+        self.check_trace_count(3)
 
     def test_exception(self):
         S = lltype.GcStruct('S', ('x', lltype.Signed))
@@ -122,7 +122,7 @@
             f(100, p3)
 
         self.meta_interp(main, [])
-        # XXX check number of bridges
+        self.check_trace_count(3)
 
 
     def test_quasi_immutable(self):
@@ -197,7 +197,7 @@
 
         x = self.meta_interp(main, [False])
         assert x < 30
-        # XXX check number of bridges
+        self.check_trace_count(4)
 
 
     def test_dont_record_repeated_guard_compatible(self):
@@ -264,8 +264,8 @@
         x = self.meta_interp(main, [])
 
         assert x < 30
-        # trace, two bridges, a finish bridge
-        self.check_trace_count(4)
+        # trace, one bridge, a finish bridge
+        self.check_trace_count(3)
 
 
     def test_order_of_chained_guards(self):
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to