[pypy-svn] r61744 - in pypy/branch/pyjitpl5/pypy: jit/backend/llgraph jit/metainterp jit/metainterp/test rlib rpython rpython/lltypesystem

fijal at codespeak.net fijal at codespeak.net
Wed Feb 11 17:58:53 CET 2009


Author: fijal
Date: Wed Feb 11 17:58:50 2009
New Revision: 61744

Added:
   pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py   (contents, props changed)
   pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rvirtualizable2.py
      - copied unchanged from r61379, pypy/branch/oo-jit/pypy/rpython/lltypesystem/rvirtualizable2.py
Modified:
   pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/codewriter.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/pyjitpl.py
   pypy/branch/pyjitpl5/pypy/jit/metainterp/test/test_virtualizable.py
   pypy/branch/pyjitpl5/pypy/rlib/jit.py
   pypy/branch/pyjitpl5/pypy/rpython/llinterp.py
   pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py
   pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py
Log:
(arigo, fijal)
Port pieces from here and there to start supporting virtualizables


Modified: pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/backend/llgraph/llimpl.py	Wed Feb 11 17:58:50 2009
@@ -80,6 +80,7 @@
     'guard_value'     : (('int', 'int'), None),
     'guard_class'     : (('ptr', 'ptr'), None),
     'guard_exception' : (('ptr',), None),
+    'guard_nonvirtualized__4' : (('ptr', 'int'), None),
     'newstr'          : (('int',), 'ptr'),
     'strlen'          : (('ptr',), 'int'),
     'strgetitem'      : (('ptr', 'int'), 'int'),
@@ -600,11 +601,11 @@
         if value != expected_value:
             raise GuardFailed
 
-    def op_guard_nonvirtualized_int(self, value, for_accessing_field):
+    def op_guard_nonvirtualized__4(self, value, for_accessing_field):
         if heaptracker.cast_vable(value).vable_rti:
             raise GuardFailed    # some other code is already in control
 
-    op_guard_nonvirtualized_ptr = op_guard_nonvirtualized_int
+    op_guard_nonvirtualized_ptr = op_guard_nonvirtualized__4
 
     def op_guard_exception(self, expected_exception):
         expected_exception = llmemory.cast_adr_to_ptr(

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	Wed Feb 11 17:58:50 2009
@@ -622,7 +622,7 @@
             try:
                 virtualizabledesc = metainterp._virtualizabledescs[TOPSTRUCT]
             except KeyError:
-                import virtualizable
+                from pypy.jit.metainterp import virtualizable
                 virtualizabledesc = virtualizable.VirtualizableDesc(
                     self.cpu, TOPSTRUCT)
                 virtualizabledesc.hash = len(metainterp._virtualizabledescs)

Modified: pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py	(original)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/heaptracker.py	Wed Feb 11 17:58:50 2009
@@ -21,20 +21,21 @@
     else:
         return lltype.cast_primitive(EXPECTED_TYPE, x)
 
-#def cast_vable(p):
-#    p = p.ptr._as_ptr()
-#    STRUCT = cast_vable_type(lltype.typeOf(p).TO)
-#    return lltype.cast_pointer(lltype.Ptr(STRUCT), p)
-
-#def cast_vable_type(STRUCT):
-#    assert STRUCT._hints.get('virtualizable2'), \
-#               "not a virtualizable2: %r" % (p,)
-#    while True:
-#        _, PARENT = STRUCT._first_struct()
-#        if PARENT is None or not PARENT._hints.get('virtualizable2'):
-#            break
-#        STRUCT = PARENT
-#    return STRUCT
+def cast_vable(p):
+    T = lltype.Ptr(lltype.typeOf(p._obj.container))
+    p = lltype.cast_opaque_ptr(T, p)
+    STRUCT = cast_vable_type(T.TO)
+    return lltype.cast_pointer(lltype.Ptr(STRUCT), p)
+
+def cast_vable_type(STRUCT):
+    assert STRUCT._hints.get('virtualizable2'), \
+           "not a virtualizable2: %r" % (p,)
+    while True:
+        _, PARENT = STRUCT._first_struct()
+        if PARENT is None or not PARENT._hints.get('virtualizable2'):
+            break
+        STRUCT = PARENT
+    return STRUCT
 
 def get_vtable_for_gcstruct(cpu, GCSTRUCT):
     # xxx hack: from a GcStruct representing an instance's

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	Wed Feb 11 17:58:50 2009
@@ -666,6 +666,8 @@
         self.builtins_keys = []
         self.builtins_values = []
         self.builtins_seen = {}
+        
+        self._virtualizabledescs = {}
 
     def generate_bytecode(self, policy):
         self._codewriter = codewriter.CodeWriter(self, policy)

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	Wed Feb 11 17:58:50 2009
@@ -1,24 +1,64 @@
 import py
-py.test.skip("XXX")
 from pypy.rpython.lltypesystem.rvirtualizable import VABLERTIPTR
-from pypy.rpython.lltypesystem import lltype, lloperation
+from pypy.rpython.lltypesystem import lltype, lloperation, rclass, llmemory
 from pypy.rpython.annlowlevel import llhelper
-from pypy.jit.hintannotator.policy import StopAtXPolicy
-from pypy.rlib.jit import hint
-from pyjitpl import get_stats
-from test.test_basic import LLJitMixin, OOJitMixin
-from test.test_specnode_vable import XY
+from pypy.jit.metainterp.policy import StopAtXPolicy
+from pypy.rlib.jit import JitDriver
+from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp import heaptracker
+from pypy.rpython.lltypesystem.rvirtualizable2 import VABLERTIPTR
+from pypy.rpython.lltypesystem.rvirtualizable2 import VirtualizableAccessor
 
 promote_virtualizable = lloperation.llop.promote_virtualizable
 debug_print = lloperation.llop.debug_print
 
+
 # ____________________________________________________________
 
-py.test.skip("XXX")
+XY = lltype.GcStruct(
+    'XY',
+    ('parent', rclass.OBJECT),
+    ('vable_base', llmemory.Address),
+    ('vable_rti', VABLERTIPTR),
+    ('x', lltype.Signed),
+    ('y', lltype.Signed),
+    hints = {'virtualizable2': True},
+    adtmeths = {'access': VirtualizableAccessor()})
+XY._adtmeths['access'].initialize(XY, ['x', 'y'])
+
+xy_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
+xy_vtable.name = lltype.malloc(rclass.OBJECT_VTABLE.name.TO, 3, immortal=True)
+xy_vtable.name[0] = 'X'
+xy_vtable.name[1] = 'Y'
+xy_vtable.name[2] = '\x00'
+heaptracker.set_testing_vtable_for_gcstruct(XY, xy_vtable)
+
+XYSUB = lltype.GcStruct(
+    'XYSUB',
+    ('parent', XY),
+    ('z', lltype.Signed),
+    hints = {'virtualizable2': True},
+    adtmeths = {'access': VirtualizableAccessor()})
+XYSUB._adtmeths['access'].initialize(XYSUB, ['z'], PARENT=XY)
+
+xysub_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
+xysub_vtable.name = lltype.malloc(rclass.OBJECT_VTABLE.name.TO, 6,
+                                  immortal=True)
+xysub_vtable.name[0] = 'X'
+xysub_vtable.name[1] = 'Y'
+xysub_vtable.name[2] = 'S'
+xysub_vtable.name[3] = 'U'
+xysub_vtable.name[4] = 'B'
+xysub_vtable.name[5] = '\x00'
+heaptracker.set_testing_vtable_for_gcstruct(XYSUB, xysub_vtable)
+
+# ____________________________________________________________
 
 class ExplicitVirtualizableTests:
 
     def test_preexisting_access(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'],
+                                virtualizables = ['xy'])
         def setup():
             xy = lltype.malloc(XY)
             xy.vable_rti = lltype.nullptr(VABLERTIPTR.TO)
@@ -27,12 +67,14 @@
             xy = setup()
             xy.x = 10
             while n > 0:
+                myjitdriver.can_enter_jit(xy=xy, n=n)
+                myjitdriver.jit_merge_point(xy=xy, n=n)
                 promote_virtualizable(lltype.Void, xy, 'x')
                 x = xy.x
                 xy.x = x + 1
                 n -= 1
         self.meta_interp(f, [5])
-        self.check_loops(getfield__4=0, setfield__4=0)
+        self.check_loops(getfield_gc__4=0, setfield_gc__4=0)
 
     def test_preexisting_access_2(self):
         def setup():

Added: pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py
==============================================================================
--- (empty file)
+++ pypy/branch/pyjitpl5/pypy/jit/metainterp/virtualizable.py	Wed Feb 11 17:58:50 2009
@@ -0,0 +1,75 @@
+
+from pypy.jit.metainterp import history
+from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.annlowlevel import llhelper
+
+class VirtualizableDesc(history.AbstractValue):
+    hash = 0
+
+    def __init__(self, cpu, TOPSTRUCT):
+        "NOT_RPYTHON"
+        initialize_virtualizable(cpu, TOPSTRUCT.access)
+        self.vable_base = cpu.offsetof(TOPSTRUCT, 'vable_base')
+        self.vable_rti  = cpu.offsetof(TOPSTRUCT, 'vable_rti')
+        self.c_vable_base = history.ConstInt(self.vable_base)
+        self.c_vable_rti  = history.ConstInt(self.vable_rti)
+
+def initialize_virtualizable(cpu, access):
+    if not hasattr(cpu, '_seen_virtualizables'):
+        cpu._seen_virtualizables = {}
+    if access in cpu._seen_virtualizables:
+        return
+    cpu._seen_virtualizables[access] = True
+    for fieldname in access.redirected_fields:
+        initialize_vable_field(cpu, access, fieldname)
+    for subaccess in access.subaccessors:
+        initialize_virtualizable(cpu, subaccess)
+    if access.parent is not None:
+        initialize_virtualizable(cpu, access.parent)
+
+def initialize_vable_field(cpu, access, fieldname):
+    FIELDTYPE = getattr(access.STRUCT, fieldname)
+    if FIELDTYPE is lltype.Void:
+        return
+    type = history.getkind_num(cpu, FIELDTYPE)
+    ofs = cpu.offsetof(access.STRUCT, fieldname)
+    getset = access.getsets[fieldname]
+
+    def getter(instanceptr):
+        rti = instanceptr.vable_rti
+        if we_are_translated():
+            rti = cast_base_ptr_to_instance(VirtualizableRTI, rti)
+        instanceptr = lltype.cast_opaque_ptr(llmemory.GCREF, instanceptr)
+        box = rti.get_field(instanceptr, ofs, type)
+        if type == 'ptr':
+            return box.getptr(RESTYPE)
+        else:
+            return lltype.cast_primitive(RESTYPE, box.getint())
+
+    def setter(instanceptr, value):
+        rti = instanceptr.vable_rti
+        if we_are_translated():
+            rti = cast_base_ptr_to_instance(VirtualizableRTI, rti)
+        instanceadr = lltype.cast_opaque_ptr(llmemory.GCREF, instanceptr)
+        if type == 'ptr':
+            valuebox = BoxPtr(llmemory.cast_ptr_to_adr(value))
+        else:
+            valuebox = BoxInt(lltype.cast_primitive(lltype.Signed, value))
+        rti.set_field(instanceadr, ofs, type, valuebox)
+
+    GETSET = lltype.typeOf(getset).TO
+    RESTYPE = GETSET.get.TO.RESULT
+    if cpu.translate_support_code:
+        mixlevelann = cpu.mixlevelann
+        getset.get = mixlevelann.delayedfunction(getter,
+                         [lltype_to_annotation(t) for t in GETSET.get.TO.ARGS],
+                         lltype_to_annotation(GETSET.get.TO.RESULT),
+                                             needtype=True)
+        getset.set = mixlevelann.delayedfunction(setter,
+                         [lltype_to_annotation(t) for t in GETSET.set.TO.ARGS],
+                         lltype_to_annotation(GETSET.set.TO.RESULT),
+                                             needtype=True)
+    else:
+        # for testing: when the cpu and the metainterp are not translated
+        getset.get = llhelper(GETSET.get, getter)
+        getset.set = llhelper(GETSET.set, setter)

Modified: pypy/branch/pyjitpl5/pypy/rlib/jit.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/rlib/jit.py	(original)
+++ pypy/branch/pyjitpl5/pypy/rlib/jit.py	Wed Feb 11 17:58:50 2009
@@ -90,13 +90,17 @@
     will allow us (later) to support a single RPython program with
     several independent JITting interpreters in it.
     """
-    def __init__(self, greens=None, reds=None):
+    def __init__(self, greens=None, reds=None, virtualizables=None):
         if greens is not None:
             self.greens = greens
         if reds is not None:
             self.reds = reds
         if not hasattr(self, 'greens') or not hasattr(self, 'reds'):
             raise AttributeError("no 'greens' or 'reds' supplied")
+        if virtualizables is not None:
+            self.virtualizables = virtualizables
+        for v in self.virtualizables:
+            assert v in self.reds
         self._alllivevars = dict.fromkeys(self.greens + self.reds)
         self._params = PARAMETERS.copy()
         if hasattr(self, 'on_enter_jit'):

Modified: pypy/branch/pyjitpl5/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/rpython/llinterp.py	(original)
+++ pypy/branch/pyjitpl5/pypy/rpython/llinterp.py	Wed Feb 11 17:58:50 2009
@@ -532,6 +532,9 @@
     def op_jit_marker(self, *args):
         pass
 
+    def op_promote_virtualizable(self, object, fieldname):
+        pass # XXX should do something
+
     def op_instrument_count(self, ll_tag, ll_label):
         pass # xxx for now
 

Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/lloperation.py	Wed Feb 11 17:58:50 2009
@@ -391,6 +391,7 @@
 
     'call_boehm_gc_alloc':  LLOp(canraise=(MemoryError,)),
     'jit_marker':           LLOp(),
+    'promote_virtualizable':LLOp(canrun=True),
 
     # __________ GC operations __________
 

Modified: pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/branch/pyjitpl5/pypy/rpython/lltypesystem/rclass.py	Wed Feb 11 17:58:50 2009
@@ -385,6 +385,9 @@
             self.rtyper.attachRuntimeTypeInfoFunc(self.object_type,
                                                   ll_runtime_type_info,
                                                   OBJECT, destrptr)
+            vtable = self.rclass.getvtable()
+            #self.rtyper.type_for_typeptr[vtable._obj] = self.lowleveltype.TO
+
     def common_repr(self): # -> object or nongcobject reprs
         return getinstancerepr(self.rtyper, None, self.gcflavor)
 
@@ -412,16 +415,17 @@
         else:
             return self.rbase.get_ll_hash_function()
 
-    def initialize_prebuilt_data(self, value, classdef, result):
+    def initialize_prebuilt_instance(self, value, classdef, result):
         if self.classdef is not None:
             # recursively build the parent part of the instance
-            self.rbase.initialize_prebuilt_data(value, classdef, result.super)
+            self.rbase.initialize_prebuilt_instance(value, classdef,
+                                                    result.super)
             # then add instance attributes from this level
             for name, (mangled_name, r) in self.fields.items():
                 if r.lowleveltype is Void:
                     llattrvalue = None
                 elif name == '_hash_cache_': # hash() support
-                    continue   # already done by initialize_prebuilt_hash()
+                    llattrvalue = hash(value)
                 else:
                     try:
                         attrvalue = getattr(value, name)
@@ -441,14 +445,6 @@
             rclass = getclassrepr(self.rtyper, classdef)
             result.typeptr = rclass.getvtable()
 
-    def initialize_prebuilt_hash(self, value, result):
-        if self.classdef is not None:
-            self.rbase.initialize_prebuilt_hash(value, result.super)
-            if '_hash_cache_' in self.fields:
-                mangled_name, r = self.fields['_hash_cache_']
-                llattrvalue = hash(value)
-                setattr(result, mangled_name, llattrvalue)
-
     def getfieldrepr(self, attr):
         """Return the repr used for the given attribute."""
         if attr in self.fields:
@@ -606,17 +602,25 @@
     if classdef is None:
         unboxed = []
         virtualizable = False
+        virtualizable2 = False
     else:
         unboxed = [subdef for subdef in classdef.getallsubdefs()
                           if subdef.classdesc.pyobj is not None and
                              issubclass(subdef.classdesc.pyobj, UnboxedValue)]
         virtualizable = classdef.classdesc.read_attribute('_virtualizable_',
                                                           Constant(False)).value
+        virtualizable2 = classdef.classdesc.read_attribute('_virtualizable2_',
+                                                           Constant(False)).value
     if virtualizable:
         assert len(unboxed) == 0
         assert gcflavor == 'gc'
         from pypy.rpython.lltypesystem import rvirtualizable
         return rvirtualizable.VirtualizableInstanceRepr(rtyper, classdef)
+    elif virtualizable2:
+        assert len(unboxed) == 0
+        assert gcflavor == 'gc'
+        from pypy.rpython.lltypesystem import rvirtualizable2
+        return rvirtualizable2.Virtualizable2InstanceRepr(rtyper, classdef)
     elif len(unboxed) == 0:
         return InstanceRepr(rtyper, classdef, gcflavor)
     else:



More information about the Pypy-commit mailing list