[pypy-svn] r65996 - in pypy/branch/pyjitpl5/pypy: jit/metainterp jit/metainterp/test rpython/ootypesystem

arigo at codespeak.net arigo at codespeak.net
Fri Jun 26 15:18:21 CEST 2009


Author: arigo
Date: Fri Jun 26 15:18:18 2009
New Revision: 65996

Modified:
   pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py
   pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py
   pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py
Log:
Just enough to make test_external_access_while_tracing pass.


Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py	Fri Jun 26 15:18:18 2009
@@ -1150,9 +1150,15 @@
 
     @specialize.arg(1)
     def execute_and_record(self, opnum, argboxes, descr=None):
-        # execute the operation first
         history.check_descr(descr)
+        # residual calls require attention to keep virtualizables in-sync
+        require_attention = (opnum == rop.CALL or opnum == rop.CALL_PURE)
+        if require_attention:
+            self.before_residual_call()
+        # execute the operation
         resbox = executor.execute(self.cpu, opnum, argboxes, descr)
+        if require_attention:
+            require_attention = self.after_residual_call()
         # check if the operation can be constant-folded away
         canfold = False
         if rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST:
@@ -1172,6 +1178,8 @@
                 and self.framestack):
                 op.pc = self.framestack[-1].pc
                 op.name = self.framestack[-1].jitcode.name
+        if require_attention:
+            self.after_generate_residual_call()
         return resbox
 
     def _interpret(self):
@@ -1474,6 +1482,39 @@
                                                         virtualizable)
             original_boxes += self.virtualizable_boxes
             self.virtualizable_boxes.append(virtualizable_box)
+            self.initialize_virtualizable_enter()
+
+    def initialize_virtualizable_enter(self):
+        vinfo = self.staticdata.virtualizable_info
+        virtualizable_box = self.virtualizable_boxes[-1]
+        virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
+        vinfo.tracing_enter(virtualizable)
+
+    def before_residual_call(self):
+        vinfo = self.staticdata.virtualizable_info
+        if vinfo is not None:
+            virtualizable_box = self.virtualizable_boxes[-1]
+            virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
+            vinfo.tracing_before_residual_call(virtualizable)
+
+    def after_residual_call(self):
+        vinfo = self.staticdata.virtualizable_info
+        if vinfo is not None:
+            virtualizable_box = self.virtualizable_boxes[-1]
+            virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
+            if vinfo.tracing_after_residual_call(virtualizable):
+                # This is before the residual call is actually generated.
+                # We first generate a store-everything-back.
+                self.gen_store_back_in_virtualizable()
+                return True    # must call after_generate_residual_call()
+        return False   # don't call after_generate_residual_call()
+
+    def after_generate_residual_call(self):
+        # Called after generating a residual call, and only if
+        # after_residual_call() returned True, i.e. if code in the residual
+        # call causes the virtualizable to escape.  Reload the modified
+        # fields of the virtualizable.
+        self.gen_load_fields_from_virtualizable()
 
     def handle_exception(self):
         etype = self.cpu.get_exception()
@@ -1500,6 +1541,7 @@
         if self.staticdata.virtualizable_info is not None:
             self.virtualizable_boxes = _consume_nums(vable_nums,
                                                      newboxes, consts)
+            self.initialize_virtualizable_enter()
             self.synchronize_virtualizable()
             #
         self.framestack = []
@@ -1521,6 +1563,27 @@
         virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
         vinfo.write_boxes(virtualizable, self.virtualizable_boxes)
 
+    def gen_load_fields_from_virtualizable(self):
+        vinfo = self.staticdata.virtualizable_info
+        if vinfo is not None:
+            vbox = self.virtualizable_boxes[-1]
+            for i in range(vinfo.num_static_extra_boxes):
+                fieldbox = self.execute_and_record(rop.GETFIELD_GC, [vbox],
+                                        descr=vinfo.static_field_descrs[i])
+                self.virtualizable_boxes[i] = fieldbox
+            i = vinfo.num_static_extra_boxes
+            virtualizable = vinfo.unwrap_virtualizable_box(vbox)
+            for k in range(vinfo.num_arrays):
+                abox = self.execute_and_record(rop.GETFIELD_GC, [vbox],
+                                         descr=vinfo.array_field_descrs[k])
+                for j in range(vinfo.get_array_length(virtualizable, k)):
+                    itembox = self.execute_and_record(rop.GETARRAYITEM_GC,
+                                                      [abox, ConstInt(j)],
+                                            descr=vinfo.array_descrs[k])
+                    self.virtualizable_boxes[i] = itembox
+                    i += 1
+            assert i + 1 == len(self.virtualizable_boxes)
+
     def gen_store_back_in_virtualizable(self):
         vinfo = self.staticdata.virtualizable_info
         if vinfo is not None:

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py	Fri Jun 26 15:18:18 2009
@@ -174,7 +174,6 @@
         self.check_loops(getfield_gc=1, setfield_gc=1)
 
     def test_external_access_while_tracing(self):
-        py.test.skip("in-progress")
         myjitdriver = JitDriver(greens = [], reds = ['n', 'm', 'xy'],
                                 virtualizables = ['xy'])
         class Outer:
@@ -202,7 +201,7 @@
         assert f(20) == 10000*20 + (20*21)/2
         res = self.meta_interp(f, [20], policy=StopAtXPolicy(ext))
         assert res == 10000*20 + (20*21)/2
-        self.check_loops(call_pure=1, getfield_gc=2, setfield_gc=2)
+        self.check_loops(call=1, getfield_gc=2, setfield_gc=2)
         # xxx for now a call that forces the virtualizable during tracing
         # is supposed to always force it later too.
 

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py	Fri Jun 26 15:18:18 2009
@@ -1,6 +1,9 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
+from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
 from pypy.rpython import rvirtualizable2
+from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.jit.metainterp.typesystem import deref
 from pypy.jit.metainterp import history
@@ -13,6 +16,15 @@
         jitdriver = warmrunnerdesc.jitdriver
         cpu = warmrunnerdesc.cpu
         self.is_oo = cpu.is_oo
+        if not self.is_oo:
+            from pypy.rpython.lltypesystem.rvirtualizable2 import VABLERTIPTR
+            self.VABLERTI = VABLERTIPTR
+            self.null_vable_rti = lltype.nullptr(VABLERTIPTR.TO)
+        else:
+            from pypy.rpython.ootypesystem.rvirtualizable2 import VABLERTI
+            self.VABLERTI = VABLERTI
+            self.null_vable_rti = ootype.make_null_instance(VABLERTI)
+        #
         assert len(jitdriver.virtualizables) == 1    # for now
         [vname] = jitdriver.virtualizables
         index = len(jitdriver.greens) + jitdriver.reds.index(vname)
@@ -155,14 +167,9 @@
         if self.is_oo:
             return      # XXX implement me
         #
-        def force_now(virtualizable):
-            rti = virtualizable.vable_rti
-            pass     # XXX in-progress
-        force_now._dont_inline_ = True
-        #
         def force_if_necessary(virtualizable):
             if virtualizable.vable_rti:
-                force_now(virtualizable)
+                self.force_now(virtualizable)
         force_if_necessary._always_inline_ = True
         #
         all_graphs = self.warmrunnerdesc.translator.graphs
@@ -188,3 +195,59 @@
 
     def is_vtypeptr(self, TYPE):
         return rvirtualizable2.match_virtualizable_type(TYPE, self.VTYPEPTR)
+
+    def cast_instance_to_base_ptr(self, vable_rti):
+        if we_are_translated():
+            return cast_instance_to_base_ptr(vable_rti)
+        else:
+            vable_rti._TYPE = self.VABLERTI   # hack for non-translated mode
+            return vable_rti
+
+    def tracing_enter(self, virtualizable):
+        if virtualizable.vable_rti:
+            self.force_now(virtualizable)
+            assert not virtualizable.vable_rti
+
+    def tracing_before_residual_call(self, virtualizable):
+        assert not virtualizable.vable_rti
+        ptr = self.cast_instance_to_base_ptr(tracing_vable_rti)
+        virtualizable.vable_rti = ptr
+
+    def tracing_after_residual_call(self, virtualizable):
+        if virtualizable.vable_rti:
+            # not modified by the residual call; assert that it is still
+            # set to 'tracing_vable_rti' and clear it.
+            ptr = self.cast_instance_to_base_ptr(tracing_vable_rti)
+            assert virtualizable.vable_rti == ptr
+            virtualizable.vable_rti = self.null_vable_rti
+            return False
+        else:
+            # marker "modified during residual call" set.
+            return True
+
+    def force_now(self, virtualizable):
+        rti = virtualizable.vable_rti
+        virtualizable.vable_rti = self.null_vable_rti
+        if we_are_translated():
+            rti = cast_base_ptr_to_instance(AbstractVableRti, rti)
+        rti.force_now(virtualizable)
+    force_now._dont_inline_ = True
+
+# ____________________________________________________________
+
+
+class AbstractVableRti(object):
+
+    def force_now(self, virtualizable):
+        raise NotImplementedError
+
+
+class TracingVableRti(AbstractVableRti):
+
+    def force_now(self, virtualizable):
+        # The values if the virtualizable are always correct during tracing.
+        # We only need to set a marker to tell that forcing occurred.
+        # As the caller resets vable_rti to NULL, it plays the role of marker.
+        pass
+
+tracing_vable_rti = TracingVableRti()

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py	Fri Jun 26 15:18:18 2009
@@ -8,7 +8,7 @@
 from pypy.rpython.test.test_llinterp import get_interpreter, clear_tcache
 from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
 from pypy.objspace.flow.model import checkgraph, Link, copygraph
-from pypy.rlib.objectmodel import we_are_translated, UnboxedValue, specialize
+from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.jit import PARAMETERS
 from pypy.rlib.rarithmetic import r_uint, intmask

Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py	(original)
+++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rclass.py	Fri Jun 26 15:18:18 2009
@@ -190,7 +190,7 @@
         self.object_type = self.lowleveltype
         self.gcflavor = gcflavor
 
-    def _setup_repr(self, hints=None):
+    def _setup_repr(self, llfields=None, hints=None):
         if hints:
             self.lowleveltype._hints.update(hints)
 
@@ -212,6 +212,9 @@
 
         fields = {}
         fielddefaults = {}
+
+        if llfields:
+            fields.update(dict(llfields))
         
         selfattrs = self.classdef.attrs
 

Modified: pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py	(original)
+++ pypy/branch/pyjitpl5/pypy/rpython/ootypesystem/rvirtualizable2.py	Fri Jun 26 15:18:18 2009
@@ -1,9 +1,11 @@
 from pypy.rpython.rmodel import inputconst
 from pypy.rpython.ootypesystem import ootype
-from pypy.rpython.ootypesystem.rclass import InstanceRepr, mangle
+from pypy.rpython.ootypesystem.rclass import InstanceRepr, mangle, OBJECT
 from pypy.rpython.rvirtualizable2 import AbstractVirtualizableAccessor
 from pypy.rpython.rvirtualizable2 import AbstractVirtualizable2InstanceRepr
 
+VABLERTI = OBJECT
+
 
 class VirtualizableAccessor(AbstractVirtualizableAccessor):
     pass
@@ -14,7 +16,10 @@
     VirtualizableAccessor = VirtualizableAccessor
 
     def _setup_repr_llfields(self):
-        return None      # TODO
+        llfields = []
+        if self.top_of_virtualizable_hierarchy:
+            llfields.append(('vable_rti', VABLERTI))
+        return llfields
 
     def get_field(self, attr):
         mangled = mangle(attr, self.rtyper.getconfig())



More information about the Pypy-commit mailing list