[pypy-svn] r76905 - in pypy/branch/gc-module/pypy: rlib rpython/memory rpython/memory/gc rpython/memory/gctransform translator/c/test
arigo at codespeak.net
arigo at codespeak.net
Mon Sep 6 19:59:47 CEST 2010
Author: arigo
Date: Mon Sep 6 19:59:45 2010
New Revision: 76905
Modified:
pypy/branch/gc-module/pypy/rlib/rgc.py
pypy/branch/gc-module/pypy/rpython/memory/gc/base.py
pypy/branch/gc-module/pypy/rpython/memory/gctransform/framework.py
pypy/branch/gc-module/pypy/rpython/memory/gctypelayout.py
pypy/branch/gc-module/pypy/translator/c/test/test_newgc.py
Log:
Implement translation of try_cast_gcref_to_instance()
using an internal helper, rgc._is_rpy_instance(),
whose answer is stored as a flag in the GC type layout.
Modified: pypy/branch/gc-module/pypy/rlib/rgc.py
==============================================================================
--- pypy/branch/gc-module/pypy/rlib/rgc.py (original)
+++ pypy/branch/gc-module/pypy/rlib/rgc.py Mon Sep 6 19:59:45 2010
@@ -309,12 +309,14 @@
# ____________________________________________________________
def get_rpy_roots():
+ "NOT_RPYTHON"
# Return the 'roots' from the GC.
# This stub is not usable on top of CPython.
# The gc typically returns a list that ends with a few NULL_GCREFs.
raise NotImplementedError
def get_rpy_referents(gcref):
+ "NOT_RPYTHON"
x = gcref._x
if isinstance(x, list):
d = x
@@ -346,6 +348,7 @@
return False # don't keep objects whose _freeze_() method explodes
def get_rpy_memory_usage(gcref):
+ "NOT_RPYTHON"
# approximate implementation using CPython's type info
Class = type(gcref._x)
size = Class.__basicsize__
@@ -385,14 +388,32 @@
def cast_instance_to_gcref(x):
# Before translation, casts an RPython instance into a _GcRef.
# After translation, it is a variant of cast_object_to_ptr(GCREF).
- return _GcRef(x)
+ if we_are_translated():
+ from pypy.rpython import annlowlevel
+ x = annlowlevel.cast_instance_to_base_ptr(x)
+ return lltype.cast_opaque_ptr(llmemory.GCREF, x)
+ else:
+ return _GcRef(x)
+cast_instance_to_gcref._annspecialcase_ = 'specialize:argtype(0)'
def try_cast_gcref_to_instance(Class, gcref):
# Before translation, unwraps the RPython instance contained in a _GcRef.
# After translation, it is a type-check performed by the GC.
- if isinstance(gcref._x, Class):
- return gcref._x
- return None
+ if we_are_translated():
+ from pypy.rpython.annlowlevel import base_ptr_lltype
+ from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
+ from pypy.rpython.lltypesystem import rclass
+ if _is_rpy_instance(gcref):
+ objptr = lltype.cast_opaque_ptr(base_ptr_lltype(), gcref)
+ clsptr = _get_llcls_from_cls(Class)
+ if rclass.ll_isinstance(objptr, clsptr):
+ return cast_base_ptr_to_instance(Class, objptr)
+ return None
+ else:
+ if isinstance(gcref._x, Class):
+ return gcref._x
+ return None
+try_cast_gcref_to_instance._annspecialcase_ = 'specialize:arg(0)'
# ------------------- implementation -------------------
@@ -425,3 +446,39 @@
vlist = hop.inputargs(hop.args_r[0])
return hop.genop('gc_get_rpy_referents', vlist,
resulttype = hop.r_result)
+
+def _is_rpy_instance(gcref):
+ "NOT_RPYTHON"
+ raise NotImplementedError
+
+def _get_llcls_from_cls(Class):
+ "NOT_RPYTHON"
+ raise NotImplementedError
+
+class Entry(ExtRegistryEntry):
+ _about_ = _is_rpy_instance
+ def compute_result_annotation(self, s_gcref):
+ from pypy.annotation import model as annmodel
+ return annmodel.SomeBool()
+ def specialize_call(self, hop):
+ vlist = hop.inputargs(hop.args_r[0])
+ return hop.genop('gc_is_rpy_instance', vlist,
+ resulttype = hop.r_result)
+
+class Entry(ExtRegistryEntry):
+ _about_ = _get_llcls_from_cls
+ def compute_result_annotation(self, s_Class):
+ from pypy.annotation import model as annmodel
+ from pypy.rpython.lltypesystem import rclass
+ assert s_Class.is_constant()
+ return annmodel.SomePtr(rclass.CLASSTYPE)
+ def specialize_call(self, hop):
+ from pypy.rpython.rclass import getclassrepr
+ from pypy.objspace.flow.model import Constant
+ from pypy.rpython.lltypesystem import rclass
+ Class = hop.args_s[0].const
+ classdef = hop.rtyper.annotator.bookkeeper.getuniqueclassdef(Class)
+ classrepr = getclassrepr(hop.rtyper, classdef)
+ vtable = classrepr.getvtable()
+ assert lltype.typeOf(vtable) == rclass.CLASSTYPE
+ return Constant(vtable, concretetype=rclass.CLASSTYPE)
Modified: pypy/branch/gc-module/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/gc-module/pypy/rpython/memory/gc/base.py (original)
+++ pypy/branch/gc-module/pypy/rpython/memory/gc/base.py Mon Sep 6 19:59:45 2010
@@ -53,7 +53,8 @@
varsize_offset_to_length,
varsize_offsets_to_gcpointers_in_var_part,
weakpointer_offset,
- member_index):
+ member_index,
+ is_rpython_class):
self.getfinalizer = getfinalizer
self.is_varsize = is_varsize
self.has_gcptr_in_varsize = has_gcptr_in_varsize
@@ -66,6 +67,7 @@
self.varsize_offsets_to_gcpointers_in_var_part = varsize_offsets_to_gcpointers_in_var_part
self.weakpointer_offset = weakpointer_offset
self.member_index = member_index
+ self.is_rpython_class = is_rpython_class
def get_member_index(self, type_id):
return self.member_index(type_id)
@@ -333,6 +335,12 @@
self._do_append_rpy_referents(gcref, result)
return result
+ # ----------
+
+ def is_rpy_instance(self, gcref):
+ typeid = self.get_type_id(llmemory.cast_ptr_to_adr(gcref))
+ return self.is_rpython_class(typeid)
+
class MovingGCBase(GCBase):
moving_gc = True
Modified: pypy/branch/gc-module/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/gc-module/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/branch/gc-module/pypy/rpython/memory/gctransform/framework.py Mon Sep 6 19:59:45 2010
@@ -396,6 +396,10 @@
[s_gc, s_gcref],
rgc.s_list_of_gcrefs(),
minimal_transform=False)
+ self.is_rpy_instance_ptr = getfn(GCClass.is_rpy_instance.im_func,
+ [s_gc, s_gcref],
+ annmodel.SomeBool(),
+ minimal_transform=False)
self.set_max_heap_size_ptr = getfn(GCClass.set_max_heap_size.im_func,
[s_gc,
@@ -907,6 +911,14 @@
resultvar=hop.spaceop.result)
self.pop_roots(hop, livevars)
+ def gct_gc_is_rpy_instance(self, hop):
+ livevars = self.push_roots(hop)
+ [v_ptr] = hop.spaceop.args
+ hop.genop("direct_call",
+ [self.is_rpy_instance_ptr, self.c_const_gc, v_ptr],
+ resultvar=hop.spaceop.result)
+ self.pop_roots(hop, livevars)
+
def gct_malloc_nonmovable_varsize(self, hop):
TYPE = hop.spaceop.result.concretetype
if self.gcdata.gc.can_malloc_nonmovable():
Modified: pypy/branch/gc-module/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/branch/gc-module/pypy/rpython/memory/gctypelayout.py (original)
+++ pypy/branch/gc-module/pypy/rpython/memory/gctypelayout.py Mon Sep 6 19:59:45 2010
@@ -100,6 +100,10 @@
infobits = self.get(typeid).infobits
return infobits & T_MEMBER_INDEX
+ def q_is_rpython_class(self, typeid):
+ infobits = self.get(typeid).infobits
+ return infobits & T_IS_RPYTHON_INSTANCE != 0
+
def set_query_functions(self, gc):
gc.set_query_functions(
self.q_is_varsize,
@@ -113,7 +117,8 @@
self.q_varsize_offset_to_length,
self.q_varsize_offsets_to_gcpointers_in_var_part,
self.q_weakpointer_offset,
- self.q_member_index)
+ self.q_member_index,
+ self.q_is_rpython_class)
# the lowest 16bits are used to store group member index
@@ -122,6 +127,7 @@
T_HAS_GCPTR_IN_VARSIZE = 0x20000
T_IS_GCARRAY_OF_GCPTR = 0x40000
T_IS_WEAKREF = 0x80000
+T_IS_RPYTHON_INSTANCE = 0x100000 # the type is a subclass of OBJECT
T_KEY_MASK = 0xFF000000
T_KEY_VALUE = 0x7A000000 # bug detection only
@@ -180,6 +186,8 @@
varinfo.varitemsize = llmemory.sizeof(ARRAY.OF)
if builder.is_weakref_type(TYPE):
infobits |= T_IS_WEAKREF
+ if is_subclass_of_object(TYPE):
+ infobits |= T_IS_RPYTHON_INSTANCE
info.infobits = infobits | T_KEY_VALUE
# ____________________________________________________________
@@ -258,9 +266,7 @@
else:
# no vtable from lltype2vtable -- double-check to be sure
# that it's not a subclass of OBJECT.
- while isinstance(TYPE, lltype.GcStruct):
- assert TYPE is not rclass.OBJECT
- _, TYPE = TYPE._first_struct()
+ assert not is_subclass_of_object(TYPE)
def get_info(self, type_id):
res = llop.get_group_member(GCData.TYPE_INFO_PTR,
@@ -436,6 +442,13 @@
for i in range(p._obj.getlength()):
zero_gc_pointers_inside(p[i], ITEM)
+def is_subclass_of_object(TYPE):
+ while isinstance(TYPE, lltype.GcStruct):
+ if TYPE is rclass.OBJECT:
+ return True
+ _, TYPE = TYPE._first_struct()
+ return False
+
########## weakrefs ##########
# framework: weakref objects are small structures containing only an address
Modified: pypy/branch/gc-module/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/gc-module/pypy/translator/c/test/test_newgc.py (original)
+++ pypy/branch/gc-module/pypy/translator/c/test/test_newgc.py Mon Sep 6 19:59:45 2010
@@ -942,6 +942,66 @@
def test_get_rpy_referents(self):
self.run("get_rpy_referents")
+ def define_is_rpy_instance(self):
+ class Foo:
+ pass
+ S = lltype.GcStruct('S', ('x', lltype.Signed))
+
+ def check(gcref, expected):
+ result = rgc._is_rpy_instance(gcref)
+ assert result == expected
+
+ def fn():
+ s = lltype.malloc(S)
+ gcref1 = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ check(gcref1, False)
+
+ f = Foo()
+ gcref3 = rgc.cast_instance_to_gcref(f)
+ check(gcref3, True)
+
+ return 0
+
+ return fn
+
+ def test_is_rpy_instance(self):
+ self.run("is_rpy_instance")
+
+ def define_try_cast_gcref_to_instance(self):
+ class Foo:
+ pass
+ class FooBar(Foo):
+ pass
+ class Biz(object):
+ pass
+ S = lltype.GcStruct('S', ('x', lltype.Signed))
+
+ def fn():
+ foo = Foo()
+ gcref1 = rgc.cast_instance_to_gcref(foo)
+ assert rgc.try_cast_gcref_to_instance(Foo, gcref1) is foo
+ assert rgc.try_cast_gcref_to_instance(FooBar, gcref1) is None
+ assert rgc.try_cast_gcref_to_instance(Biz, gcref1) is None
+
+ foobar = FooBar()
+ gcref2 = rgc.cast_instance_to_gcref(foobar)
+ assert rgc.try_cast_gcref_to_instance(Foo, gcref2) is foobar
+ assert rgc.try_cast_gcref_to_instance(FooBar, gcref2) is foobar
+ assert rgc.try_cast_gcref_to_instance(Biz, gcref2) is None
+
+ s = lltype.malloc(S)
+ gcref3 = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ assert rgc.try_cast_gcref_to_instance(Foo, gcref3) is None
+ assert rgc.try_cast_gcref_to_instance(FooBar, gcref3) is None
+ assert rgc.try_cast_gcref_to_instance(Biz, gcref3) is None
+
+ return 0
+
+ return fn
+
+ def test_try_cast_gcref_to_instance(self):
+ self.run("try_cast_gcref_to_instance")
+
class TestSemiSpaceGC(TestUsingFramework, snippet.SemiSpaceGCTestDefines):
gcpolicy = "semispace"
More information about the Pypy-commit
mailing list