[pypy-svn] r65866 - in pypy/branch/pyjitpl5/pypy: jit/metainterp jit/metainterp/test rpython/lltypesystem

arigo at codespeak.net arigo at codespeak.net
Mon Jun 22 17:40:04 CEST 2009


Author: arigo
Date: Mon Jun 22 17:40:03 2009
New Revision: 65866

Modified:
   pypy/branch/pyjitpl5/pypy/jit/metainterp/TODO
   pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/warmspot.py
   pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py
Log:
Restart support for virtualizables, now done in codewriter.py and
pyjitpl.py.


Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/TODO
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/TODO	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/TODO	Mon Jun 22 17:40:03 2009
@@ -7,3 +7,5 @@
 * kill empty pairs setup_exception_block/teardown_exception_block
 
 * long term: memory management of the compiled code (free old code)
+
+* 'resume_info' should be shared (see pyjitpl.py)

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py	Mon Jun 22 17:40:03 2009
@@ -791,6 +791,13 @@
         RESULT = op.result.concretetype
         if RESULT is lltype.Void:
             return
+        # check for virtualizable
+        if self.is_virtualizable_getset(op):
+            vinfo = self.codewriter.metainterp_sd.virtualizable_info
+            index = vinfo.field_to_extra_box[op.args[1].value]
+            self.emit('getfield_vable', index)
+            self.register_var(op.result)
+            return
         # check for deepfrozen structures that force constant-folding
         if deref(v_inst.concretetype)._hints.get('immutable'):
             pure = '_pure'
@@ -816,6 +823,12 @@
         RESULT = v_value.concretetype
         if RESULT is lltype.Void:
             return
+        # check for virtualizable
+        if self.is_virtualizable_getset(op):
+            vinfo = self.codewriter.metainterp_sd.virtualizable_info
+            index = vinfo.field_to_extra_box[op.args[1].value]
+            self.emit('setfield_vable', index, self.var_position(v_value))
+            return
         argname = getattr(deref(v_inst.concretetype), '_gckind', 'gc')
         self.emit('setfield_%s' % (argname,))
         self.emit(self.var_position(v_inst))
@@ -830,6 +843,15 @@
         return (op.args[1].value == 'typeptr' and
                 deref(op.args[0].concretetype)._hints.get('typeptr'))
 
+    def is_virtualizable_getset(self, op):
+        # XXX check more carefully; for now assumes that every access of
+        # an object of exactly the type VTYPEPTR is a virtualizable access
+        vinfo = self.codewriter.metainterp_sd.virtualizable_info
+        if vinfo is not None:
+            return op.args[0].concretetype == vinfo.VTYPEPTR
+        else:
+            return False
+
     def handle_getfield_typeptr(self, op):
         # special-casing for getting the typeptr of an object
         self.minimize_variables()

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/compile.py	Mon Jun 22 17:40:03 2009
@@ -240,8 +240,10 @@
 
 
 class ResumeGuardDescr(AbstractDescr):
-    def __init__(self, resume_info, consts, history, history_guard_index):
+    def __init__(self, resume_info, vable_nums, consts,
+                 history, history_guard_index):
         self.resume_info = resume_info
+        self.vable_nums = vable_nums      # None if no virtualizable
         self.counter = 0
         self.history = history
         assert history_guard_index >= 0

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	Mon Jun 22 17:40:03 2009
@@ -460,6 +460,14 @@
     def opimpl_setfield_raw(self, box, fielddesc, valuebox):
         self.execute(rop.SETFIELD_RAW, [box, valuebox], descr=fielddesc)
 
+    @arguments("int")
+    def opimpl_getfield_vable(self, index):
+        resbox = self.metainterp.virtualizable_boxes[index]
+        self.make_result_box(resbox)
+    @arguments("int", "box")
+    def opimpl_setfield_vable(self, index, valuebox):
+        self.metainterp.virtualizable_boxes[index] = valuebox
+
     def perform_call(self, jitcode, varargs):
         if (isinstance(self.metainterp.history, history.BlackHole) and
             jitcode.calldescr is not None):
@@ -729,13 +737,7 @@
             check_args(*liveboxes)
         self.pc = pc
         self.exception_target = exception_target
-        self.env = []
-        for num in nums:
-            if num >= 0:
-                box = liveboxes[num]
-            else:
-                box = consts[~num]
-            self.env.append(box)
+        self.env = _consume_nums(nums, liveboxes, consts)
         if DEBUG >= 2:
             values = ' '.join([box.repr_rpython() for box in self.env])
             log('setup_resume_at_op  %s:%d [%s] %d' % (self.jitcode.name,
@@ -761,7 +763,8 @@
     def generate_guard(self, pc, opnum, box, extraargs=[]):
         if isinstance(box, Const):    # no need for a guard
             return
-        if isinstance(self.metainterp.history, history.BlackHole):
+        metainterp = self.metainterp
+        if isinstance(metainterp.history, history.BlackHole):
             return
         saved_pc = self.pc
         self.pc = pc
@@ -771,30 +774,22 @@
         liveboxes = []
         consts = []
         memo = {}
-        for frame in self.metainterp.framestack:
-            nums = []
-            for framebox in frame.env:
-                assert framebox is not None
-                if isinstance(framebox, Box):
-                    try:
-                        num = memo[framebox]
-                    except KeyError:
-                        num = len(liveboxes)
-                        memo[framebox] = num
-                        liveboxes.append(framebox)
-                else:
-                    num = ~len(consts)
-                    consts.append(framebox)
-                nums.append(num)
+        if metainterp.staticdata.virtualizable_info is None:
+            vable_nums = None
+        else:
+            vable_nums = _generate_nums(metainterp.virtualizable_boxes,
+                                        memo, liveboxes, consts)
+        for frame in metainterp.framestack:
+            nums = _generate_nums(frame.env, memo, liveboxes, consts)
             resume_info.append((frame.jitcode, frame.pc, nums,
                                 frame.exception_target))
         if box is not None:
             moreargs = [box] + extraargs
         else:
             moreargs = list(extraargs)
-        guard_op = self.metainterp.history.record(opnum, moreargs, None)
-        resumedescr = compile.ResumeGuardDescr(resume_info, consts,
-            self.metainterp.history, len(self.metainterp.history.operations)-1)
+        guard_op = metainterp.history.record(opnum, moreargs, None)
+        resumedescr = compile.ResumeGuardDescr(resume_info, vable_nums, consts,
+            metainterp.history, len(metainterp.history.operations)-1)
         op = history.ResOperation(rop.FAIL, liveboxes, None, descr=resumedescr)
         guard_op.suboperations = [op]
         self.pc = saved_pc
@@ -827,7 +822,37 @@
 
 # ____________________________________________________________
 
+def _generate_nums(frameboxes, memo, liveboxes, consts):
+    nums = []
+    for framebox in frameboxes:
+        assert framebox is not None
+        if isinstance(framebox, Box):
+            try:
+                num = memo[framebox]
+            except KeyError:
+                num = len(liveboxes)
+                memo[framebox] = num
+                liveboxes.append(framebox)
+        else:
+            num = ~len(consts)
+            consts.append(framebox)
+        nums.append(num)
+    return nums
+
+def _consume_nums(nums, liveboxes, consts):
+    env = []
+    for num in nums:
+        if num >= 0:
+            box = liveboxes[num]
+        else:
+            box = consts[~num]
+        env.append(box)
+    return env
+
+# ____________________________________________________________
+
 class MetaInterpStaticData(object):
+    virtualizable_info = None
 
     def __init__(self, portal_graph, graphs, cpu, stats, options,
                  optimizer=None, profile=None, warmrunnerdesc=None):
@@ -1109,6 +1134,8 @@
             return self.designate_target_loop(gmp)
 
     def reached_can_enter_jit(self, live_arg_boxes):
+        if self.staticdata.virtualizable_info is not None:
+            live_arg_boxes += self.virtualizable_boxes
         # Called whenever we reach the 'can_enter_jit' hint.
         # First, attempt to make a bridge:
         # - if self.resumekey is a ResumeGuardDescr, it starts from a guard
@@ -1274,34 +1301,8 @@
 
     def _initialize_from_start(self, original_boxes, num_green_args, *args):
         if args:
-            value = args[0]
-            if isinstance(lltype.typeOf(value), lltype.Ptr):
-                if lltype.typeOf(value).TO._gckind == 'gc':
-                    value = lltype.cast_opaque_ptr(llmemory.GCREF, value)
-                    if num_green_args > 0:
-                        cls = ConstPtr
-                    else:
-                        cls = BoxPtr
-                else:
-                    adr = llmemory.cast_ptr_to_adr(value)
-                    value = self.cpu.cast_adr_to_int(adr)
-                    if num_green_args > 0:
-                        cls = ConstInt
-                    else:
-                        cls = BoxInt
-            elif isinstance(lltype.typeOf(value), ootype.OOType):
-                value = ootype.cast_to_object(value)
-                if num_green_args > 0:
-                    cls = ConstObj
-                else:
-                    cls = BoxObj
-            else:
-                if num_green_args > 0:
-                    cls = ConstInt
-                else:
-                    cls = BoxInt
-                value = intmask(value)
-            box = cls(value)
+            from pypy.jit.metainterp.warmspot import wrap
+            box = wrap(self.cpu, args[0], num_green_args > 0)
             original_boxes.append(box)
             self._initialize_from_start(original_boxes, num_green_args-1,
                                         *args[1:])
@@ -1318,6 +1319,7 @@
         f = self.newframe(self.staticdata.portal_code)
         f.pc = 0
         f.env = original_boxes[:]
+        self.initialize_virtualizable(original_boxes)
         return original_boxes
 
     def initialize_state_from_guard_failure(self, guard_failure):
@@ -1347,9 +1349,21 @@
             # the BlackHole is invalid because it doesn't start with
             # guard_failure.key.guard_op.suboperations, but that's fine
         self.rebuild_state_after_failure(resumedescr.resume_info,
+                                         resumedescr.vable_nums,
                                          resumedescr.consts,
                                          guard_failure.args)
 
+    def initialize_virtualizable(self, original_boxes):
+        vinfo = self.staticdata.virtualizable_info
+        if vinfo is not None:
+            virtualizable_box = original_boxes[vinfo.index_in_boxes]
+            virtualizable = virtualizable_box.getptr(vinfo.VTYPEPTR)
+            # The field 'virtualizable_boxes' is not even present
+            # if 'virtualizable_info' is None.  Check for that first.
+            self.virtualizable_boxes = vinfo.read_boxes(self.cpu,
+                                                        virtualizable)
+            original_boxes += self.virtualizable_boxes
+
     def handle_exception(self):
         etype = self.cpu.get_exception()
         evalue = self.cpu.get_exc_value()
@@ -1368,9 +1382,13 @@
             frame.generate_guard(frame.pc, rop.GUARD_NO_EXCEPTION, None, [])
             return False
 
-    def rebuild_state_after_failure(self, resume_info, consts, newboxes):
+    def rebuild_state_after_failure(self, resume_info, vable_nums, consts,
+                                    newboxes):
         if not we_are_translated():
             self._debug_history.append(['guard_failure', None, None])
+        if self.staticdata.virtualizable_info is not None:
+            self.virtualizable_boxes = _consume_nums(vable_nums,
+                                                     newboxes, consts)
         self.framestack = []
         for jitcode, pc, nums, exception_target in resume_info:
             f = self.newframe(jitcode)

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	Mon Jun 22 17:40:03 2009
@@ -43,7 +43,6 @@
         return xy
 
     def test_preexisting_access(self):
-        py.test.skip("bugs")
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'],
                                 virtualizables = ['xy'])
         def f(n):

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	Mon Jun 22 17:40:03 2009
@@ -131,6 +131,8 @@
         self.build_meta_interp(**kwds)
         self.make_args_specification()
         self.rewrite_jit_merge_point()
+        if self.jitdriver.virtualizables:
+            self.metainterp_sd.virtualizable_info = VirtualizableInfo(self)
         self.metainterp_sd.generate_bytecode(policy, self.ts)
         self.make_enter_function()
         self.rewrite_can_enter_jit()
@@ -463,6 +465,34 @@
             call_final_function(self.translator, finish_profiler,
                                 annhelper = self.annhelper)
 
+class VirtualizableInfo:
+    def __init__(self, warmrunnerdesc):
+        jitdriver = warmrunnerdesc.jitdriver
+        assert len(jitdriver.virtualizables) == 1    # for now
+        [vname] = jitdriver.virtualizables
+        index = len(jitdriver.greens) + jitdriver.reds.index(vname)
+        VTYPEPTR = warmrunnerdesc.JIT_ENTER_FUNCTYPE.ARGS[index]
+        fields = VTYPEPTR.TO._adtmeths['access'].redirected_fields
+        self.VTYPEPTR = VTYPEPTR
+        self.index_in_boxes = index
+        self.num_extra_boxes = len(fields)
+        self.field_to_extra_box = dict([(name, i)
+                                        for (i, name) in enumerate(fields)])
+        #
+        def read_boxes(cpu, virtualizable):
+            boxes = []
+            for fieldname in unroll_fields:
+                x = getattr(virtualizable, fieldname)
+                boxes.append(wrap(cpu, x))
+            return boxes
+        #
+        unroll_fields = unrolling_iterable(fields)
+        self.read_boxes = read_boxes
+
+    def _freeze_(self):
+        return True
+
+
 def decode_hp_hint_args(op):
     # Returns (list-of-green-vars, list-of-red-vars) without Voids.
     assert op.opname == 'jit_marker'
@@ -486,6 +516,32 @@
         return lltype.cast_primitive(TYPE, box.getint())
 unwrap._annspecialcase_ = 'specialize:arg(0)'
 
+def wrap(cpu, value, in_const_box=False):
+    if isinstance(lltype.typeOf(value), lltype.Ptr):
+        if lltype.typeOf(value).TO._gckind == 'gc':
+            value = lltype.cast_opaque_ptr(llmemory.GCREF, value)
+            if in_const_box:
+                return history.ConstPtr(value)
+            else:
+                return history.BoxPtr(value)
+        else:
+            adr = llmemory.cast_ptr_to_adr(value)
+            value = cpu.cast_adr_to_int(adr)
+            # fall through to the end of the function
+    elif isinstance(lltype.typeOf(value), ootype.OOType):
+        value = ootype.cast_to_object(value)
+        if in_const_box:
+            return history.ConstObj(value)
+        else:
+            return history.BoxObj(value)
+    else:
+        value = intmask(value)
+    if in_const_box:
+        return history.ConstInt(value)
+    else:
+        return history.BoxInt(value)
+wrap._annspecialcase_ = 'specialize:llargtype(1)'
+
 def equal_whatever(TYPE, x, y):
     if isinstance(TYPE, lltype.Ptr):
         if TYPE.TO is rstr.STR or TYPE.TO is rstr.UNICODE:

Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py	(original)
+++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py	Mon Jun 22 17:40:03 2009
@@ -24,6 +24,7 @@
             # as long as no valid pointer has been put in the structure
             # by the JIT, accessing the fields should raise, in order
             # to prevent constant-folding
+            import py
             py.test.raises(lltype.UninitializedMemoryAccess, "getset.get")
             py.test.raises(lltype.UninitializedMemoryAccess, "getset.set")
             self.getsets[fieldname] = getset



More information about the Pypy-commit mailing list