[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