[pypy-svn] pypy numpy-exp: Refactor virtualizable.py to actually allow multiple jits with virtualizables

fijal commits-noreply at bitbucket.org
Sun Feb 13 16:16:01 CET 2011


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: numpy-exp
Changeset: r41877:e211d75bf89f
Date: 2011-02-11 22:02 +0200
http://bitbucket.org/pypy/pypy/changeset/e211d75bf89f/

Log:	Refactor virtualizable.py to actually allow multiple jits with
	virtualizables in one compiled executable

diff --git a/pypy/jit/metainterp/resume.py b/pypy/jit/metainterp/resume.py
--- a/pypy/jit/metainterp/resume.py
+++ b/pypy/jit/metainterp/resume.py
@@ -1007,17 +1007,16 @@
             return len(numb.nums)
         index = len(numb.nums) - 1
         virtualizable = self.decode_ref(numb.nums[index])
-        virtualizable = vinfo.cast_gcref_to_vtype(virtualizable)
         if self.resume_after_guard_not_forced == 1:
             # in the middle of handle_async_forcing()
-            assert virtualizable.vable_token
-            virtualizable.vable_token = vinfo.TOKEN_NONE
+            assert vinfo.gettoken(virtualizable)
+            vinfo.settoken(virtualizable, vinfo.TOKEN_NONE)
         else:
             # just jumped away from assembler (case 4 in the comment in
             # virtualizable.py) into tracing (case 2); check that vable_token
             # is and stays 0.  Note the call to reset_vable_token() in
             # warmstate.py.
-            assert not virtualizable.vable_token
+            assert not vinfo.gettoken(virtualizable)
         return vinfo.write_from_resume_data_partial(virtualizable, self, numb)
 
     def load_value_of_type(self, TYPE, tagged):

diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -2151,7 +2151,7 @@
             # warmstate.py.
             virtualizable_box = self.virtualizable_boxes[-1]
             virtualizable = vinfo.unwrap_virtualizable_box(virtualizable_box)
-            assert not virtualizable.vable_token
+            assert not vinfo.gettoken(virtualizable)
             # fill the virtualizable with the local boxes
             self.synchronize_virtualizable()
         #

diff --git a/pypy/jit/metainterp/test/test_ztranslation.py b/pypy/jit/metainterp/test/test_ztranslation.py
--- a/pypy/jit/metainterp/test/test_ztranslation.py
+++ b/pypy/jit/metainterp/test/test_ztranslation.py
@@ -29,6 +29,12 @@
             def __init__(self, i):
                 self.i = i
 
+        class OtherFrame(object):
+            _virtualizable2_ = ['i']
+
+            def __init__(self, i):
+                self.i = i
+
         class JitCellCache:
             entry = None
         jitcellcache = JitCellCache()
@@ -61,18 +67,20 @@
                 frame.i -= 1
             return total * 10
         #
-        myjitdriver2 = JitDriver(greens = ['g'], reds = ['m', 'x', 's'])
+        myjitdriver2 = JitDriver(greens = ['g'], reds = ['m', 's', 'f'],
+                                 virtualizables = ['f'])
         def f2(g, m, x):
             s = ""
+            f = OtherFrame(x)
             while m > 0:
-                myjitdriver2.can_enter_jit(g=g, m=m, x=x, s=s)
-                myjitdriver2.jit_merge_point(g=g, m=m, x=x, s=s)
+                myjitdriver2.can_enter_jit(g=g, m=m, f=f, s=s)
+                myjitdriver2.jit_merge_point(g=g, m=m, f=f, s=s)
                 s += 'xy'
                 if s[:2] == 'yz':
                     return -666
                 m -= 1
-                x += 3
-            return x
+                f.i += 3
+            return f.i
         #
         def main(i, j):
             return f(i) - f2(i+j, i, j)
@@ -124,9 +132,7 @@
                                      type_system=self.type_system,
                                      optimizer=OPTIMIZER_FULL,
                                      ProfilerClass=Profiler)
-        assert res == main(40)
-
-
+        assert res == main(40)        
 
 class TestTranslationLLtype(TranslationTest):
 

diff --git a/pypy/jit/metainterp/virtualizable.py b/pypy/jit/metainterp/virtualizable.py
--- a/pypy/jit/metainterp/virtualizable.py
+++ b/pypy/jit/metainterp/virtualizable.py
@@ -1,4 +1,4 @@
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
 from pypy.rpython import rvirtualizable2
@@ -8,7 +8,7 @@
 from pypy.jit.metainterp.typesystem import deref, fieldType, arrayItem
 from pypy.jit.metainterp import history
 from pypy.jit.metainterp.warmstate import wrap, unwrap
-
+from pypy.rlib.objectmodel import specialize
 
 class VirtualizableInfo:
     TOKEN_NONE            = 0      # must be 0 -- see also x86.call_assembler
@@ -76,6 +76,8 @@
         setarrayitem = cpu.ts.setarrayitem
         #
         def read_boxes(cpu, virtualizable):
+            assert lltype.typeOf(virtualizable) == llmemory.GCREF
+            virtualizable = cast_gcref_to_vtype(virtualizable)
             boxes = []
             for _, fieldname in unroll_static_fields:
                 x = getattr(virtualizable, fieldname)
@@ -87,6 +89,7 @@
             return boxes
         #
         def write_boxes(virtualizable, boxes):
+            virtualizable = cast_gcref_to_vtype(virtualizable)
             i = 0
             for FIELDTYPE, fieldname in unroll_static_fields:
                 x = unwrap(FIELDTYPE, boxes[i])
@@ -101,6 +104,7 @@
             assert len(boxes) == i + 1
         #
         def write_from_resume_data_partial(virtualizable, reader, numb):
+            virtualizable = cast_gcref_to_vtype(virtualizable)
             # Load values from the reader (see resume.py) described by
             # the list of numbers 'nums', and write them in their proper
             # place in the 'virtualizable'.  This works from the end of
@@ -124,6 +128,7 @@
             return i
         #
         def load_list_of_boxes(virtualizable, reader, numb):
+            virtualizable = cast_gcref_to_vtype(virtualizable)
             # Uses 'virtualizable' only to know the length of the arrays;
             # does not write anything into it.  The returned list is in
             # the format expected of virtualizable_boxes, so it ends in
@@ -147,6 +152,7 @@
             return boxes
         #
         def check_boxes(virtualizable, boxes):
+            virtualizable = cast_gcref_to_vtype(virtualizable)
             # for debugging
             i = 0
             for FIELDTYPE, fieldname in unroll_static_fields:
@@ -162,6 +168,7 @@
             assert len(boxes) == i + 1
         #
         def get_index_in_array(virtualizable, arrayindex, index):
+            virtualizable = cast_gcref_to_vtype(virtualizable)
             index += self.num_static_extra_boxes
             j = 0
             for _, fieldname in unroll_array_fields:
@@ -173,6 +180,7 @@
             assert False, "invalid arrayindex"
         #
         def get_array_length(virtualizable, arrayindex):
+            virtualizable = cast_gcref_to_vtype(virtualizable)
             j = 0
             for _, fieldname in unroll_array_fields:
                 if arrayindex == j:
@@ -197,6 +205,70 @@
         self.get_index_in_array = get_index_in_array
         self.get_array_length = get_array_length
 
+        def cast_to_vtype(virtualizable):
+            return self.cpu.ts.cast_to_instance_maybe(VTYPEPTR, virtualizable)
+        self.cast_to_vtype = cast_to_vtype
+
+        def cast_gcref_to_vtype(virtualizable):
+            assert lltype.typeOf(virtualizable) == llmemory.GCREF
+            return lltype.cast_opaque_ptr(VTYPEPTR, virtualizable)
+        self.cast_gcref_to_vtype = cast_gcref_to_vtype
+
+        def reset_vable_token(virtualizable):
+            virtualizable.vable_token = VirtualizableInfo.TOKEN_NONE
+        self.reset_vable_token = reset_vable_token
+
+        def clear_vable_token(virtualizable):
+            virtualizable = cast_gcref_to_vtype(virtualizable)
+            if virtualizable.vable_token:
+                force_now(virtualizable)
+                assert not virtualizable.vable_token
+        self.clear_vable_token = clear_vable_token
+
+        def tracing_before_residual_call(virtualizable):
+            virtualizable = cast_gcref_to_vtype(virtualizable)
+            assert not virtualizable.vable_token
+            virtualizable.vable_token = VirtualizableInfo.TOKEN_TRACING_RESCALL
+        self.tracing_before_residual_call = tracing_before_residual_call
+
+        def tracing_after_residual_call(virtualizable):
+            virtualizable = cast_gcref_to_vtype(virtualizable)
+            if virtualizable.vable_token:
+                # not modified by the residual call; assert that it is still
+                # set to TOKEN_TRACING_RESCALL and clear it.
+                assert virtualizable.vable_token == VirtualizableInfo.TOKEN_TRACING_RESCALL
+                virtualizable.vable_token = VirtualizableInfo.TOKEN_NONE
+                return False
+            else:
+                # marker "modified during residual call" set.
+                return True
+        self.tracing_after_residual_call = tracing_after_residual_call
+
+        def force_now(virtualizable):
+            token = virtualizable.vable_token
+            if token == VirtualizableInfo.TOKEN_TRACING_RESCALL:
+                # The values in the virtualizable are always correct during
+                # tracing.  We only need to reset vable_token to TOKEN_NONE
+                # as a marker for the tracing, to tell it that this
+                # virtualizable escapes.
+                virtualizable.vable_token = VirtualizableInfo.TOKEN_NONE
+            else:
+                from pypy.jit.metainterp.compile import ResumeGuardForcedDescr
+                ResumeGuardForcedDescr.force_now(cpu, token)
+                assert virtualizable.vable_token == VirtualizableInfo.TOKEN_NONE
+        force_now._dont_inline_ = True
+        self.force_now = force_now
+
+        def gettoken(virtualizable):
+            virtualizable = cast_gcref_to_vtype(virtualizable)
+            return virtualizable.vable_token
+        self.gettoken = gettoken
+
+        def settoken(virtualizable, token):
+            virtualizable = cast_gcref_to_vtype(virtualizable)
+            virtualizable.vable_token = token
+        self.settoken = settoken
+
     def _freeze_(self):
         return True
 
@@ -216,55 +288,11 @@
             all_graphs, self.VTYPEPTR, funcptr)
 
     def unwrap_virtualizable_box(self, virtualizable_box):
-        return virtualizable_box.getref(self.VTYPEPTR)
-
-    def cast_to_vtype(self, virtualizable):
-        return self.cpu.ts.cast_to_instance_maybe(self.VTYPEPTR, virtualizable)
-    cast_to_vtype._annspecialcase_ = 'specialize:ll'
-
-    def cast_gcref_to_vtype(self, virtualizable):
-        return lltype.cast_opaque_ptr(self.VTYPEPTR, virtualizable)
-
+        return virtualizable_box.getref(llmemory.GCREF)
+     
     def is_vtypeptr(self, TYPE):
         return rvirtualizable2.match_virtualizable_type(TYPE, self.VTYPEPTR)
 
-    def reset_vable_token(self, virtualizable):
-        virtualizable.vable_token = self.TOKEN_NONE
-
-    def clear_vable_token(self, virtualizable):
-        if virtualizable.vable_token:
-            self.force_now(virtualizable)
-            assert not virtualizable.vable_token
-
-    def tracing_before_residual_call(self, virtualizable):
-        assert not virtualizable.vable_token
-        virtualizable.vable_token = self.TOKEN_TRACING_RESCALL
-
-    def tracing_after_residual_call(self, virtualizable):
-        if virtualizable.vable_token:
-            # not modified by the residual call; assert that it is still
-            # set to TOKEN_TRACING_RESCALL and clear it.
-            assert virtualizable.vable_token == self.TOKEN_TRACING_RESCALL
-            virtualizable.vable_token = self.TOKEN_NONE
-            return False
-        else:
-            # marker "modified during residual call" set.
-            return True
-
-    def force_now(self, virtualizable):
-        token = virtualizable.vable_token
-        if token == self.TOKEN_TRACING_RESCALL:
-            # The values in the virtualizable are always correct during
-            # tracing.  We only need to reset vable_token to TOKEN_NONE
-            # as a marker for the tracing, to tell it that this
-            # virtualizable escapes.
-            virtualizable.vable_token = self.TOKEN_NONE
-        else:
-            from pypy.jit.metainterp.compile import ResumeGuardForcedDescr
-            ResumeGuardForcedDescr.force_now(self.cpu, token)
-            assert virtualizable.vable_token == self.TOKEN_NONE
-    force_now._dont_inline_ = True
-
 # ____________________________________________________________
 #
 # The 'vable_token' field of a virtualizable is either 0, -1, or points


More information about the Pypy-commit mailing list