[pypy-svn] r74833 - in pypy/branch/blackhole-improvement/pypy/jit: codewriter codewriter/test metainterp metainterp/test

arigo at codespeak.net arigo at codespeak.net
Fri May 28 09:55:31 CEST 2010


Author: arigo
Date: Fri May 28 09:55:28 2010
New Revision: 74833

Modified:
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py
   pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/compile.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/history.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/resume.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_virtualizable.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/virtualizable.py
   pypy/branch/blackhole-improvement/pypy/jit/metainterp/warmspot.py
Log:
Start working on virtualizables.


Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/call.py	Fri May 28 09:55:28 2010
@@ -16,6 +16,7 @@
 
 class CallControl(object):
     virtualref_info = None     # optionally set from outside
+    virtualizable_info = None  # optionally set from outside
     portal_runner_ptr = None   # optionally set from outside
 
     def __init__(self, cpu=None, portal_graph=None):

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/codewriter.py	Fri May 28 09:55:28 2010
@@ -62,15 +62,24 @@
         self.assembler.assemble(ssarepr, jitcode)
 
     def make_jitcodes(self, verbose=False):
+        log.info("making JitCodes...")
         maingraph = self.portal_graph
         self.mainjitcode = self.callcontrol.get_jitcode(maingraph)
+        count = 0
         for graph, jitcode in self.callcontrol.enum_pending_graphs():
             self.transform_graph_to_jitcode(graph, jitcode,
                                             graph is maingraph, verbose)
+            count += 1
+            if not count % 500:
+                log.info("Produced %d jitcodes" % count)
+        log.info("there are %d JitCode instances." % count)
 
     def setup_vrefinfo(self, vrefinfo):
         self.callcontrol.virtualref_info = vrefinfo
 
+    def setup_virtualizable_info(self, vinfo):
+        self.callcontrol.virtualizable_info = vinfo
+
     def setup_portal_runner_ptr(self, portal_runner_ptr):
         self.callcontrol.portal_runner_ptr = portal_runner_ptr
 

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/jtransform.py	Fri May 28 09:55:28 2010
@@ -37,6 +37,8 @@
         if block.operations == ():
             return
         self.immutable_arrays = {}
+        self.vable_array_vars = {}
+        self.vable_flags = {}
         renamings = {}
         renamings_constants = {}    # subset of 'renamings', {Var:Const} only
         newoperations = []
@@ -177,6 +179,7 @@
     def rewrite_op_cast_int_to_unichar(self, op): pass
     def rewrite_op_cast_int_to_uint(self, op): pass
     def rewrite_op_cast_uint_to_int(self, op): pass
+    def rewrite_op_resume_point(self, op): pass
 
     def _rewrite_symmetric(self, op):
         """Rewrite 'c1+v2' into 'v2+c1' in an attempt to avoid generating
@@ -406,6 +409,15 @@
         assert ARRAY._gckind == 'gc'
         if self._array_of_voids(ARRAY):
             return []
+        if op.args[0] in self.vable_array_vars:     # for virtualizables
+            vars = self.vable_array_vars[op.args[0]]
+            (v_base, arrayfielddescr, arraydescr) = vars
+            kind = getkind(op.result.concretetype)
+            return [SpaceOperation('-live-', [], None),
+                    SpaceOperation('getarrayitem_vable_%s' % kind,
+                                   [v_base, arrayfielddescr, arraydescr,
+                                    op.args[1]], op.result)]
+        # normal case follows
         arraydescr = self.cpu.arraydescrof(ARRAY)
         kind = getkind(op.result.concretetype)
         return SpaceOperation('getarrayitem_gc_%s' % kind[0],
@@ -417,6 +429,14 @@
         assert ARRAY._gckind == 'gc'
         if self._array_of_voids(ARRAY):
             return []
+        if op.args[0] in self.vable_array_vars:     # for virtualizables
+            vars = self.vable_array_vars[op.args[0]]
+            (v_base, arrayfielddescr, arraydescr) = vars
+            kind = getkind(op.result.concretetype)
+            return [SpaceOperation('-live-', [], None),
+                    SpaceOperation('setarrayitem_vable_%s' % kind,
+                                   [v_base, arrayfielddescr, arraydescr,
+                                    op.args[1], op.args[2]], None)]
         arraydescr = self.cpu.arraydescrof(ARRAY)
         kind = getkind(op.args[2].concretetype)
         return SpaceOperation('setarrayitem_gc_%s' % kind[0],
@@ -426,6 +446,14 @@
     def rewrite_op_getarraysize(self, op):
         ARRAY = op.args[0].concretetype.TO
         assert ARRAY._gckind == 'gc'
+        if op.args[0] in self.vable_array_vars:     # for virtualizables
+            vars = self.vable_array_vars[op.args[0]]
+            (v_base, arrayfielddescr, arraydescr) = vars
+            return [SpaceOperation('-live-', [], None),
+                    SpaceOperation('arraylen_vable',
+                                   [v_base, arrayfielddescr, arraydescr],
+                                   op.result)]
+        # normal case follows
         arraydescr = self.cpu.arraydescrof(ARRAY)
         return SpaceOperation('arraylen_gc', [op.args[0], arraydescr],
                               op.result)
@@ -445,21 +473,23 @@
         if RESULT is lltype.Void:
             return
         # check for virtualizable
-        #try:
-        #    if self.is_virtualizable_getset(op):
-        #        vinfo = self.codewriter.metainterp_sd.virtualizable_info
-        #        index = vinfo.static_field_to_extra_box[op.args[1].value]
-        #        self.emit('getfield_vable',
-        #                  self.var_position(v_inst),
-        #                  index)
-        #        self.register_var(op.result)
-        #        return
-        #except VirtualizableArrayField:
-        #    # xxx hack hack hack
-        #    vinfo = self.codewriter.metainterp_sd.virtualizable_info
-        #    arrayindex = vinfo.array_field_counter[op.args[1].value]
-        #    self.vable_array_vars[op.result] = (op.args[0], arrayindex)
-        #    return
+        try:
+            if self.is_virtualizable_getset(op):
+                descr = self.get_virtualizable_field_descr(op.args[1].value)
+                kind = getkind(RESULT)[0]
+                return [SpaceOperation('-live-', [], None),
+                        SpaceOperation('getfield_vable_%s' % kind,
+                                       [v_inst, descr], op.result)]
+        except VirtualizableArrayField:
+            # xxx hack hack hack
+            vinfo = self.callcontrol.virtualizable_info
+            arrayindex = vinfo.array_field_counter[op.args[1].value]
+            arrayfielddescr = vinfo.array_field_descrs[arrayindex]
+            arraydescr = vinfo.array_descrs[arrayindex]
+            self.vable_array_vars[op.result] = (op.args[0],
+                                                arrayfielddescr,
+                                                arraydescr)
+            return []
         # check for deepfrozen structures that force constant-folding
         hints = v_inst.concretetype.TO._hints
         accessor = hints.get("immutable_fields")
@@ -488,14 +518,12 @@
         if RESULT is lltype.Void:
             return
         # check for virtualizable
-        #if self.is_virtualizable_getset(op):
-        #    vinfo = self.codewriter.metainterp_sd.virtualizable_info
-        #    index = vinfo.static_field_to_extra_box[op.args[1].value]
-        #    self.emit('setfield_vable',
-        #              self.var_position(v_inst),
-        #              index,
-        #              self.var_position(v_value))
-        #    return
+        if self.is_virtualizable_getset(op):
+            descr = self.get_virtualizable_field_descr(op.args[1].value)
+            kind = getkind(RESULT)[0]
+            return [SpaceOperation('-live-', [], None),
+                    SpaceOperation('setfield_vable_%s' % kind,
+                                   [v_inst, descr, v_value], None)]
         argname = getattr(v_inst.concretetype.TO, '_gckind', 'gc')
         descr = self.cpu.fielddescrof(v_inst.concretetype.TO,
                                       c_fieldname.value)
@@ -508,6 +536,35 @@
         return (op.args[1].value == 'typeptr' and
                 op.args[0].concretetype.TO._hints.get('typeptr'))
 
+    def is_virtualizable_getset(self, op):
+        # every access of an object of exactly the type VTYPEPTR is
+        # likely to be a virtualizable access, but we still have to
+        # check it in pyjitpl.py.
+        try:
+            vinfo = self.callcontrol.virtualizable_info
+        except AttributeError:
+            return False
+        if vinfo is None or not vinfo.is_vtypeptr(op.args[0].concretetype):
+            return False
+        res = False
+        if op.args[1].value in vinfo.static_field_to_extra_box:
+            res = True
+        if op.args[1].value in vinfo.array_fields:
+            res = VirtualizableArrayField(self.graph)
+
+        if res:
+            flags = self.vable_flags[op.args[0]]
+            if 'fresh_virtualizable' in flags:
+                return False
+        if isinstance(res, Exception):
+            raise res
+        return res
+
+    def get_virtualizable_field_descr(self, fieldname):
+        vinfo = self.callcontrol.virtualizable_info
+        index = vinfo.static_field_to_extra_box[fieldname]
+        return vinfo.static_field_descrs[index]
+
     def handle_getfield_typeptr(self, op):
         if isinstance(op.args[0], Constant):
             cls = op.args[0].value.typeptr
@@ -892,11 +949,24 @@
     def rewrite_op_jit_force_virtual(self, op):
         return self._do_builtin_call(op)
 
+    def rewrite_op_jit_force_virtualizable(self, op):
+        # this one is for virtualizables
+        vinfo = self.callcontrol.virtualizable_info
+        assert vinfo is not None
+        assert vinfo.is_vtypeptr(op.args[0].concretetype)
+        self.vable_flags[op.args[0]] = op.args[2].value
+        return []
+
 # ____________________________________________________________
 
 class NotSupported(Exception):
     pass
 
+class VirtualizableArrayField(Exception):
+    def __str__(self):
+        return "using virtualizable array in illegal way in %r" % (
+            self.args[0],)
+
 def _with_prefix(prefix):
     result = {}
     for name in dir(Transformer):

Modified: pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/codewriter/test/test_flatten.py	Fri May 28 09:55:28 2010
@@ -69,6 +69,8 @@
     def found_jitdriver(self, jitdriver):
         assert isinstance(jitdriver, JitDriver)
         self.jitdriver = jitdriver
+    def getjitdriver(self):
+        return self.jitdriver
 
 class FakeCallControlWithVRefInfo:
     class virtualref_info:

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/blackhole.py	Fri May 28 09:55:28 2010
@@ -907,6 +907,11 @@
         cpu.bh_setarrayitem_gc_f(arraydescr, items, index, nval)
 
     # ----------
+    # virtualizables operations
+
+    #xxx
+
+    # ----------
     # the following operations are directly implemented by the backend
 
     @arguments("cpu", "i", "d", "R", returns="i")
@@ -1035,6 +1040,10 @@
     bhimpl_getfield_gc_r_pure = bhimpl_getfield_gc_r
     bhimpl_getfield_gc_f_pure = bhimpl_getfield_gc_f
 
+    bhimpl_getfield_vable_i = bhimpl_getfield_gc_i
+    bhimpl_getfield_vable_r = bhimpl_getfield_gc_r
+    bhimpl_getfield_vable_f = bhimpl_getfield_gc_f
+
     @arguments("cpu", "i", "d", returns="i")
     def bhimpl_getfield_raw_i(cpu, struct, fielddescr):
         return cpu.bh_getfield_raw_i(struct, fielddescr)
@@ -1059,6 +1068,10 @@
     def bhimpl_setfield_gc_f(cpu, struct, fielddescr, newvalue):
         cpu.bh_setfield_gc_f(struct, fielddescr, newvalue)
 
+    bhimpl_setfield_vable_i = bhimpl_setfield_gc_i
+    bhimpl_setfield_vable_r = bhimpl_setfield_gc_r
+    bhimpl_setfield_vable_f = bhimpl_setfield_gc_f
+
     @arguments("cpu", "i", "d", "i")
     def bhimpl_setfield_raw_i(cpu, struct, fielddescr, newvalue):
         cpu.bh_setfield_raw_i(struct, fielddescr, newvalue)
@@ -1254,8 +1267,7 @@
     blackholeinterp = blackhole_from_resumedata(
         metainterp_sd.blackholeinterpbuilder,
         resumedescr,
-        False,
-        all_virtuals)  # XXX
+        all_virtuals)
     # XXX virtualizable
     current_exc = blackholeinterp._prepare_resume_from_failure(
         resumedescr.guard_opnum)

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/compile.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/compile.py	Fri May 28 09:55:28 2010
@@ -349,8 +349,7 @@
         from pypy.jit.metainterp.resume import force_from_resumedata
         metainterp_sd = self.metainterp_sd
         expect_virtualizable = metainterp_sd.virtualizable_info is not None
-        all_virtuals = force_from_resumedata(metainterp_sd, self,
-                                            expect_virtualizable)
+        all_virtuals = force_from_resumedata(metainterp_sd, self)
         # Handle virtualizable_boxes: store them on the real virtualizable now
         if expect_virtualizable:
             metainterp_sd.virtualizable_info.forced_vable(virtualizable_boxes)

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/history.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/history.py	Fri May 28 09:55:28 2010
@@ -40,6 +40,7 @@
         return "ref"
     else:
         raise NotImplementedError("type %s not supported" % TYPE)
+getkind._annspecialcase_ = 'specialize:memo'
 
 def repr_pointer(box):
     from pypy.rpython.lltypesystem import rstr

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/pyjitpl.py	Fri May 28 09:55:28 2010
@@ -516,9 +516,9 @@
             self.metainterp.replace_box(box, standard_box)
         return not isstandard
 
-    def _get_virtualizable_field_descr(self, index):
+    def _get_virtualizable_field_index(self, fielddescr):
         vinfo = self.metainterp.staticdata.virtualizable_info
-        return vinfo.static_field_descrs[index]
+        return vinfo.static_field_by_descrs[fielddescr]
 
     def _get_virtualizable_array_field_descr(self, index):
         vinfo = self.metainterp.staticdata.virtualizable_info
@@ -528,23 +528,32 @@
         vinfo = self.metainterp.staticdata.virtualizable_info
         return vinfo.array_descrs[index]
 
-    @FixME  #arguments("orgpc", "box", "int")
-    def opimpl_getfield_vable(self, pc, basebox, index):
-        if self._nonstandard_virtualizable(pc, basebox):
-            self.execute_with_descr(rop.GETFIELD_GC, self._get_virtualizable_field_descr(index), basebox)
-            return
+    @arguments("orgpc", "box", "descr")
+    def _opimpl_getfield_vable(self, pc, box, fielddescr):
+        if self._nonstandard_virtualizable(pc, box):
+            return self.execute_with_descr(rop.GETFIELD_GC, fielddescr, box)
         self.metainterp.check_synchronized_virtualizable()
-        resbox = self.metainterp.virtualizable_boxes[index]
-        self.make_result_box(resbox)
-    @FixME  #arguments("orgpc", "box", "int", "box")
-    def opimpl_setfield_vable(self, pc, basebox, index, valuebox):
-        if self._nonstandard_virtualizable(pc, basebox):
-            self.execute_with_descr(rop.SETFIELD_GC, self._get_virtualizable_field_descr(index), basebox, valuebox)
+        index = self._get_virtualizable_field_index(fielddescr)
+        return self.metainterp.virtualizable_boxes[index]
+
+    opimpl_getfield_vable_i = _opimpl_getfield_vable
+    opimpl_getfield_vable_r = _opimpl_getfield_vable
+    opimpl_getfield_vable_f = _opimpl_getfield_vable
+
+    @arguments("orgpc", "box", "descr", "box")
+    def _opimpl_setfield_vable(self, pc, box, fielddescr, valuebox):
+        if self._nonstandard_virtualizable(pc, box):
+            self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox)
             return
+        index = self._get_virtualizable_field_index(fielddescr)
         self.metainterp.virtualizable_boxes[index] = valuebox
         self.metainterp.synchronize_virtualizable()
         # XXX only the index'th field needs to be synchronized, really
 
+    opimpl_setfield_vable_i = _opimpl_setfield_vable
+    opimpl_setfield_vable_r = _opimpl_setfield_vable
+    opimpl_setfield_vable_f = _opimpl_setfield_vable
+
     def _get_arrayitem_vable_index(self, pc, arrayindex, indexbox):
         indexbox = self.implement_guard_value(pc, indexbox)
         vinfo = self.metainterp.staticdata.virtualizable_info
@@ -1112,6 +1121,7 @@
         self.portal_code = codewriter.mainjitcode
         self._portal_runner_ptr = codewriter.callcontrol.portal_runner_ptr
         self.virtualref_info = codewriter.callcontrol.virtualref_info
+        self.virtualizable_info = codewriter.callcontrol.virtualizable_info
         RESULT = codewriter.portal_graph.getreturnvar().concretetype
         self.result_type = history.getkind(RESULT)
         #
@@ -1862,9 +1872,7 @@
     def rebuild_state_after_failure(self, resumedescr):
         vinfo = self.staticdata.virtualizable_info
         self.framestack = []
-        expect_virtualizable = vinfo is not None
-        boxlists = resume.rebuild_from_resumedata(self, resumedescr,
-                                                  expect_virtualizable)
+        boxlists = resume.rebuild_from_resumedata(self, resumedescr, vinfo)
         inputargs_and_holes, virtualizable_boxes, virtualref_boxes = boxlists
         #
         # virtual refs: make the vrefs point to the freshly allocated virtuals
@@ -1880,11 +1888,6 @@
         # boxes, in whichever direction is appropriate
         if expect_virtualizable:
             self.virtualizable_boxes = virtualizable_boxes
-            if 0:  ## self._already_allocated_resume_virtuals is not None:
-                # resuming from a ResumeGuardForcedDescr: load the new values
-                # currently stored on the virtualizable fields
-                self.load_fields_from_virtualizable()
-                return
             # 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

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/resume.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/resume.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/resume.py	Fri May 28 09:55:28 2010
@@ -1,10 +1,10 @@
 import sys, os
-from pypy.jit.metainterp.history import Box, Const, ConstInt
+from pypy.jit.metainterp.history import Box, Const, ConstInt, getkind
 from pypy.jit.metainterp.history import BoxInt, BoxPtr, BoxFloat
 from pypy.jit.metainterp.history import INT, REF, FLOAT, HOLE
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.metainterp import jitprof
-from pypy.rpython.lltypesystem import rffi
+from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rlib import rarithmetic
 from pypy.rlib.objectmodel import we_are_translated, specialize
 from pypy.rlib.debug import have_debug_prints
@@ -57,9 +57,11 @@
     storage.rd_frame_info_list = frame_info_list
     snapshot = Snapshot(top.parent_resumedata_snapshot,
                         top.get_list_of_active_boxes(False))
-    snapshot = Snapshot(snapshot, virtualref_boxes[:]) # xxx for now
     if virtualizable_boxes is not None:
-        snapshot = Snapshot(snapshot, virtualizable_boxes[:]) # xxx for now
+        boxes = virtualref_boxes + virtualizable_boxes
+    else:
+        boxes = virtualref_boxes[:]
+    snapshot = Snapshot(snapshot, boxes)
     storage.rd_snapshot = snapshot
 
 class Numbering(object):
@@ -548,11 +550,10 @@
 
 # ---------- when resuming for pyjitpl.py, make boxes ----------
 
-def rebuild_from_resumedata(metainterp, storage,
-                            expects_virtualizables):
+def rebuild_from_resumedata(metainterp, storage, virtualizable_info):
     resumereader = ResumeDataBoxReader(storage, metainterp)
     virtualizable_boxes = None
-    if expects_virtualizables:
+    if virtualizable_info:
         XXX # virtualizable_boxes = resumereader.consume_boxes()
     virtualref_boxes = resumereader.consume_virtualref_boxes()
     frameinfo = storage.rd_frame_info_list
@@ -679,13 +680,12 @@
 # ---------- when resuming for blackholing, get direct values ----------
 
 def blackhole_from_resumedata(blackholeinterpbuilder, storage,
-                              expects_virtualizables, all_virtuals=None):
+                              all_virtuals=None):
     resumereader = ResumeDataDirectReader(blackholeinterpbuilder.cpu, storage,
                                           all_virtuals)
-    if expects_virtualizables:
-        XXX
+    vinfo = blackholeinterpbuilder.metainterp_sd.virtualizable_info
     vrefinfo = blackholeinterpbuilder.metainterp_sd.virtualref_info
-    resumereader.consume_virtualref_info(vrefinfo)
+    resumereader.consume_vref_and_vable(vrefinfo, vinfo)
     #
     # First get a chain of blackhole interpreters whose length is given
     # by the depth of rd_frame_info_list.  The first one we get must be
@@ -715,9 +715,8 @@
     resumereader.done()
     return firstbh
 
-def force_from_resumedata(metainterp_sd, storage, expects_virtualizables):
+def force_from_resumedata(metainterp_sd, storage):
     resumereader = ResumeDataDirectReader(metainterp_sd.cpu, storage)
-    virtualizable_boxes = None
     if expects_virtualizables:
         XXX
     vrefinfo = metainterp_sd.virtualref_info
@@ -725,6 +724,7 @@
     return resumereader.virtuals
 
 class ResumeDataDirectReader(AbstractResumeDataReader):
+    resume_after_guard_not_forced = False
 
     def __init__(self, cpu, storage, all_virtuals=None):
         self._init(cpu, storage)
@@ -733,6 +733,7 @@
         else:
             # special case for resuming after a GUARD_NOT_FORCED: we already
             # have the virtuals
+            self.resume_after_guard_not_forced = True
             self.virtuals = all_virtuals
 
     def consume_one_section(self, blackholeinterp):
@@ -740,17 +741,51 @@
         info = blackholeinterp.get_current_position_info()
         self._prepare_next_section(info)
 
-    def consume_virtualref_info(self, vrefinfo):
+    def consume_virtualref_info(self, vrefinfo, nums, end):
         # we have to decode a list of references containing pairs
-        # [..., virtual, vref, ...]
-        nums = self.cur_numb.nums
-        self.cur_numb = self.cur_numb.prev
-        for i in range(0, len(nums), 2):
+        # [..., virtual, vref, ...]  stopping at 'end'
+        assert (end & 1) == 0
+        for i in range(0, end, 2):
             virtual = self.decode_ref(nums[i])
             vref = self.decode_ref(nums[i+1])
             # For each pair, we store the virtual inside the vref.
             vrefinfo.continue_tracing(vref, virtual)
 
+    def consume_vable_info(self, vinfo, nums):
+        # we have to ignore the initial part of 'nums' (containing vrefs),
+        # find the virtualizable from nums[-1], load all other values
+        # from the CPU stack, and copy them into the virtualizable
+        if vinfo is None:
+            return len(nums)
+        virtualizable = self.decode_ref(nums[-1])
+        virtualizable = vinfo.cast_gcref_to_vtype(virtualizable)
+        # 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
+        return vinfo.write_from_resume_data(virtualizable, self, nums)
+
+    def load_value_of_type(self, TYPE, tagged):
+        kind = getkind(TYPE)
+        if kind == 'int':
+            x = self.decode_int(tagged)
+        elif kind == 'ref':
+            x = self.decode_ref(tagged)
+        elif kind == 'float':
+            x = self.decode_float(tagged)
+        else:
+            raise AssertionError(kind)
+        return lltype._cast_whatever(TYPE, x)
+    load_value_of_type._annspecialcase_ = 'specialize:arg(1)'
+
+    def consume_vref_and_vable(self, vrefinfo, vinfo):
+        nums = self.cur_numb.nums
+        self.cur_numb = self.cur_numb.prev
+        if not self.resume_after_guard_not_forced:
+            end_vref = self.consume_vable_info(vinfo, nums)
+            self.consume_virtualref_info(vrefinfo, nums, end_vref)
+
     def allocate_with_vtable(self, known_class):
         from pypy.jit.metainterp.executor import exec_new_with_vtable
         return exec_new_with_vtable(self.cpu, known_class)

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_virtualizable.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_virtualizable.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/test/test_virtualizable.py	Fri May 28 09:55:28 2010
@@ -2,14 +2,15 @@
 from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.rpython.lltypesystem import lltype, lloperation, rclass, llmemory
 from pypy.rpython.annlowlevel import llhelper
-from pypy.jit.metainterp.policy import StopAtXPolicy
+from pypy.jit.codewriter.policy import StopAtXPolicy
+from pypy.jit.codewriter import heaptracker
 from pypy.rlib.jit import JitDriver, hint, dont_look_inside
 from pypy.rlib.jit import OPTIMIZER_SIMPLE, OPTIMIZER_FULL
 from pypy.rlib.rarithmetic import intmask
 from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
 from pypy.rpython.rclass import FieldListAccessor
 from pypy.jit.metainterp.warmspot import get_stats, get_translator
-from pypy.jit.metainterp import history, heaptracker
+from pypy.jit.metainterp import history
 from pypy.jit.metainterp.test.test_optimizefindnode import LLtypeMixin
 
 def promote_virtualizable(*args):

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/virtualizable.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/virtualizable.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/virtualizable.py	Fri May 28 09:55:28 2010
@@ -72,6 +72,8 @@
                                     for name in static_fields]
         self.array_field_descrs = [cpu.fielddescrof(VTYPE, name)
                                    for name in array_fields]
+        self.static_field_by_descrs = dict(
+            [(descr, i) for (i, descr) in enumerate(self.static_field_descrs)])
         #
         getlength = cpu.ts.getlength
         getarrayitem = cpu.ts.getarrayitem
@@ -102,6 +104,21 @@
                     i = i + 1
             assert len(boxes) == i + 1
         #
+        def write_from_resume_data(virtualizable, reader, nums):
+            # similar to write_boxes(), but works from the end instead
+            i = len(nums) - 1
+            for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev:
+                lst = getattr(virtualizable, fieldname)
+                for j in range(getlength(lst)-1, -1, -1):
+                    i -= 1
+                    x = reader.load_value_of_type(ARRAYITEMTYPE, nums[i])
+                    setarrayitem(lst, j, x)
+            for FIELDTYPE, fieldname in unroll_static_fields_rev:
+                i -= 1
+                x = reader.load_value_of_type(FIELDTYPE, nums[i])
+                setattr(virtualizable, fieldname, x)
+            return i
+        #
         def check_boxes(virtualizable, boxes):
             # for debugging
             i = 0
@@ -141,8 +158,13 @@
                                                       static_fields))
         unroll_array_fields = unrolling_iterable(zip(ARRAYITEMTYPES,
                                                      array_fields))
+        unroll_static_fields_rev = unrolling_iterable(
+                                          reversed(list(unroll_static_fields)))
+        unroll_array_fields_rev  = unrolling_iterable(
+                                          reversed(list(unroll_array_fields)))
         self.read_boxes = read_boxes
         self.write_boxes = write_boxes
+        self.write_from_resume_data = write_from_resume_data
         self.check_boxes = check_boxes
         self.get_index_in_array = get_index_in_array
         self.get_array_length = get_array_length
@@ -172,6 +194,9 @@
         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)
+
     def is_vtypeptr(self, TYPE):
         return rvirtualizable2.match_virtualizable_type(TYPE, self.VTYPEPTR)
 

Modified: pypy/branch/blackhole-improvement/pypy/jit/metainterp/warmspot.py
==============================================================================
--- pypy/branch/blackhole-improvement/pypy/jit/metainterp/warmspot.py	(original)
+++ pypy/branch/blackhole-improvement/pypy/jit/metainterp/warmspot.py	Fri May 28 09:55:28 2010
@@ -167,7 +167,8 @@
         self.codewriter.setup_vrefinfo(vrefinfo)
         if self.jitdriver.virtualizables:
             from pypy.jit.metainterp.virtualizable import VirtualizableInfo
-            self.metainterp_sd.virtualizable_info = VirtualizableInfo(self)
+            self.virtualizable_info = VirtualizableInfo(self)
+            self.codewriter.setup_virtualizable_info(self.virtualizable_info)
         #
         self.make_exception_classes()
         self.make_driverhook_graphs()
@@ -183,7 +184,7 @@
         self.metainterp_sd.finish_setup(self.codewriter, optimizer=optimizer)
 
     def finish(self):
-        vinfo = self.metainterp_sd.virtualizable_info
+        vinfo = self.virtualizable_info
         if vinfo is not None:
             vinfo.finish()
         if self.cpu.translate_support_code:
@@ -556,7 +557,7 @@
             self.PTR_PORTAL_FUNCTYPE.TO.RESULT)
         self.codewriter.setup_portal_runner_ptr(self.portal_runner_ptr)
 
-        vinfo = self.metainterp_sd.virtualizable_info
+        vinfo = self.virtualizable_info
 
         def assembler_call_helper(failindex, virtualizableref):
             fail_descr = self.cpu.get_fail_descr_from_number(failindex)



More information about the Pypy-commit mailing list