[pypy-svn] r68545 - in pypy/branch/tagged-pointers-framework2/pypy: config lang/prolog/interpreter lang/smalltalk rlib rlib/test rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory rpython/memory/gc rpython/memory/gctransform rpython/memory/test rpython/test translator/c/gcc/test translator/c/test
cfbolz at codespeak.net
cfbolz at codespeak.net
Fri Oct 16 23:02:22 CEST 2009
Author: cfbolz
Date: Fri Oct 16 23:02:19 2009
New Revision: 68545
Modified:
pypy/branch/tagged-pointers-framework2/pypy/config/pypyoption.py
pypy/branch/tagged-pointers-framework2/pypy/config/translationoption.py
pypy/branch/tagged-pointers-framework2/pypy/lang/prolog/interpreter/term.py
pypy/branch/tagged-pointers-framework2/pypy/lang/smalltalk/model.py
pypy/branch/tagged-pointers-framework2/pypy/rlib/objectmodel.py
pypy/branch/tagged-pointers-framework2/pypy/rlib/test/test_objectmodel.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/llmemory.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/lltype.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/rtagged.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/test/test_rtagged.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/base.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/generation.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/hybrid.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/markcompact.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/marksweep.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/semispace.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gctransform/asmgcroot.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gctransform/framework.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gcwrapper.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/test/test_gc.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/test/test_transformed_gc.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/rclass.py
pypy/branch/tagged-pointers-framework2/pypy/rpython/test/test_rptr.py
pypy/branch/tagged-pointers-framework2/pypy/translator/c/gcc/test/test_asmgcroot.py
pypy/branch/tagged-pointers-framework2/pypy/translator/c/test/test_newgc.py
pypy/branch/tagged-pointers-framework2/pypy/translator/c/test/test_rtagged.py
Log:
merge in tagged-pointers-framework branch:
-----------------------------------------------------------------------
r65789 | arigo | 2009-06-16 10:06:57 +0200 (Tue, 16 Jun 2009) | 3 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/generation.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/framework.py
Missing a gc.points_to_valid_gc_object() in the thread-specific code.
The rest is just clean-ups.
------------------------------------------------------------------------
r65784 | arigo | 2009-06-15 22:02:59 +0200 (Mon, 15 Jun 2009) | 4 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/asmgcroot.py
M /pypy/branch/tagged-pointers-framework/pypy/translator/c/gcc/test/test_asmgcroot.py
Revert r65770. It turns out that asmgcc is not compatible with non-moving GCs.
It could be fixed but it's not worthwhile (and definitely the "fix" of r65770
was completely broken :-)
------------------------------------------------------------------------
r65770 | cfbolz | 2009-06-14 12:21:20 +0200 (Sun, 14 Jun 2009) | 3 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/asmgcroot.py
M /pypy/branch/tagged-pointers-framework/pypy/translator/c/gcc/test/test_asmgcroot.py
Make asmgcc work at least somewhat with non-moving GCs. In the current form,
some of the tests segfault, no clue whose fault that is yet.
------------------------------------------------------------------------
r65751 | cfbolz | 2009-06-12 19:12:45 +0200 (Fri, 12 Jun 2009) | 3 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/hybrid.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py
Fix id computation in the presence of tagged pointers: make sure that real
objects have even ids, so that the tagged ints can have odd ones.
------------------------------------------------------------------------
r65456 | cfbolz | 2009-05-27 15:59:42 +0200 (Wed, 27 May 2009) | 3 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py
Be more precise about getting the type of tagged-or-normal-or-None. Gets rid of
a lot of warnings when translating.
------------------------------------------------------------------------
r65454 | cfbolz | 2009-05-27 15:04:33 +0200 (Wed, 27 May 2009) | 2 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/asmgcroot.py
M /pypy/branch/tagged-pointers-framework/pypy/translator/c/gcc/test/test_asmgcroot.py
Fix asmgcroot stack walker in conjunction with tagged pointers.
------------------------------------------------------------------------
r65453 | cfbolz | 2009-05-27 15:03:14 +0200 (Wed, 27 May 2009) | 2 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/lang/smalltalk/model.py
Adapt smalltalk vm to make the translation.taggedpointers option do something.
------------------------------------------------------------------------
r65452 | cfbolz | 2009-05-27 15:02:21 +0200 (Wed, 27 May 2009) | 2 lines
Changed paths:
A /pypy/branch/tagged-pointers-framework/pypy/doc/config/translation.taggedpointers.txt
add documentation
------------------------------------------------------------------------
r65448 | cfbolz | 2009-05-27 14:18:39 +0200 (Wed, 27 May 2009) | 2 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_rtagged.py
fix another test
------------------------------------------------------------------------
r65447 | cfbolz | 2009-05-27 14:16:22 +0200 (Wed, 27 May 2009) | 2 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rlib/test/test_objectmodel.py
forgot to fix a test
------------------------------------------------------------------------
r65422 | cfbolz | 2009-05-26 17:40:45 +0200 (Tue, 26 May 2009) | 3 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py
waaaaaa, how could this ever have worked? type(x) where x=None but x could also
be a tagged pointer segfaulted so far.
------------------------------------------------------------------------
r65420 | cfbolz | 2009-05-26 15:10:34 +0200 (Tue, 26 May 2009) | 2 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/lang/prolog/interpreter/term.py
make it possible to use tagged pointers in the prolog implementation.
------------------------------------------------------------------------
r65415 | cfbolz | 2009-05-25 17:44:47 +0200 (Mon, 25 May 2009) | 3 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rlib/objectmodel.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rtagged.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py
Rename the very generic method name "getvalue" to get_untagged_value. So far
it's not really used much anyway, only in tests.
------------------------------------------------------------------------
r65414 | cfbolz | 2009-05-25 17:39:35 +0200 (Mon, 25 May 2009) | 2 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rlib/objectmodel.py
update comment
------------------------------------------------------------------------
r65413 | cfbolz | 2009-05-25 17:26:28 +0200 (Mon, 25 May 2009) | 2 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_boehm.py
M /pypy/branch/tagged-pointers-framework/pypy/translator/c/test/test_newgc.py
Fix translating tagging tests to use the new option.
------------------------------------------------------------------------
r65412 | cfbolz | 2009-05-25 17:22:29 +0200 (Mon, 25 May 2009) | 5 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/config/pypyoption.py
M /pypy/branch/tagged-pointers-framework/pypy/config/translationoption.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/rclass.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/test/test_rtagged.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py
Add a translation config option to use pointer tagging. This should make it
possible for e.g. the Smalltalk VM to make pointer tagging a translate.py (as it
is not really natural there to have to different classes as in the Python
interpreter).
------------------------------------------------------------------------
r65409 | cfbolz | 2009-05-25 14:25:19 +0200 (Mon, 25 May 2009) | 5 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/llmemory.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/lltype.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/hybrid.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/test/test_rptr.py
- fix casting of opaque pointers to ints. Needed for correct GCREF handing
- allowing casting of addresses of dead objects to int. Fixes some
test_transformed_gc tests
- proper id handling of tagged pointers in moving GCs
------------------------------------------------------------------------
r65133 | cfbolz | 2009-05-07 14:00:26 +0200 (Thu, 07 May 2009) | 3 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/framework.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py
tests with prebuilt data structures. This finds a bug. The tests still fails on
mark-n-sweep, no clue why yet.
------------------------------------------------------------------------
r65083 | cfbolz | 2009-05-06 12:26:50 +0200 (Wed, 06 May 2009) | 3 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gcwrapper.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py
Fix gcwrapper to support prebuilt tagged pointers. Doesn't find the bug I am
hunting though.
------------------------------------------------------------------------
r65079 | cfbolz | 2009-05-06 09:55:29 +0200 (Wed, 06 May 2009) | 2 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/generation.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py
fix write barrier
------------------------------------------------------------------------
r65078 | cfbolz | 2009-05-06 09:39:43 +0200 (Wed, 06 May 2009) | 2 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/markcompact.py
missed a copy of trace
------------------------------------------------------------------------
r65041 | cfbolz | 2009-05-04 23:35:44 +0200 (Mon, 04 May 2009) | 2 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/config/pypyoption.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py
In theory, this should be enough. In practise, it obviously segfaults.
------------------------------------------------------------------------
r65021 | cfbolz | 2009-05-04 13:59:29 +0200 (Mon, 04 May 2009) | 4 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/generation.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/markcompact.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/marksweep.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/semispace.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gctransform/framework.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gcwrapper.py
Refactor things so that there is only one place where it is checked whether a
pointed-to object is NULL. This place can later be used for checking tagged
pointers as well.
------------------------------------------------------------------------
r65020 | cfbolz | 2009-05-04 13:58:19 +0200 (Mon, 04 May 2009) | 2 lines
Changed paths:
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py
M /pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py
(failing) tests that I would like to pass
------------------------------------------------------------------------
r65019 | cfbolz | 2009-05-04 13:54:06 +0200 (Mon, 04 May 2009) | 2 lines
Changed paths:
A /pypy/branch/tagged-pointers-framework (from /pypy/trunk:65018)
A branch to play with supporting tagged pointers with the framework GCs
Modified: pypy/branch/tagged-pointers-framework2/pypy/config/pypyoption.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/config/pypyoption.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/config/pypyoption.py Fri Oct 16 23:02:19 2009
@@ -184,8 +184,8 @@
BoolOption("withsmallint", "use tagged integers",
default=False,
- requires=[("translation.gc", "boehm"),
- ("objspace.std.withprebuiltint", False)]),
+ requires=[("objspace.std.withprebuiltint", False),
+ ("translation.taggedpointers", True)]),
BoolOption("withprebuiltint", "prebuild commonly used int objects",
default=False),
Modified: pypy/branch/tagged-pointers-framework2/pypy/config/translationoption.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/config/translationoption.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/config/translationoption.py Fri Oct 16 23:02:19 2009
@@ -169,6 +169,10 @@
IntOption("withsmallfuncsets",
"Represent groups of less funtions than this as indices into an array",
default=0),
+ BoolOption("taggedpointers",
+ "When true, enable the use of tagged pointers. "
+ "If false, use normal boxing",
+ default=False),
# options for ootype
OptionDescription("ootype", "Object Oriented Typesystem options", [
Modified: pypy/branch/tagged-pointers-framework2/pypy/lang/prolog/interpreter/term.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/lang/prolog/interpreter/term.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/lang/prolog/interpreter/term.py Fri Oct 16 23:02:19 2009
@@ -26,10 +26,6 @@
__slots__ = ()
_immutable_ = True
- def __init__(self):
- raise NotImplementedError("abstract base class")
- return self
-
def getvalue(self, heap):
return self
@@ -270,12 +266,11 @@
error.throw_type_error("evaluable", self.get_prolog_signature())
-class Number(NonVar):
+class Number(NonVar, UnboxedValue):
TAG = tag()
STANDARD_ORDER = 2
_immutable_ = True
- def __init__(self, num):
- self.num = num
+ __slots__ = ("num", )
@specialize.arg(3)
def basic_unify(self, other, heap, occurs_check=False):
Modified: pypy/branch/tagged-pointers-framework2/pypy/lang/smalltalk/model.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/lang/smalltalk/model.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/lang/smalltalk/model.py Fri Oct 16 23:02:19 2009
@@ -19,7 +19,7 @@
from pypy.rlib.rarithmetic import intmask
from pypy.lang.smalltalk import constants, error
from pypy.tool.pairtype import extendabletype
-from pypy.rlib.objectmodel import instantiate
+from pypy.rlib.objectmodel import instantiate, UnboxedValue
from pypy.rlib.bitmanipulation import splitter
class W_Object(object):
@@ -96,14 +96,15 @@
False means swapping failed"""
return False
-class W_SmallInteger(W_Object):
+
+# the UnboxedValue mixin means the object can potentially be stored in unboxed
+# form
+
+class W_SmallInteger(W_Object, UnboxedValue):
"""Boxed integer value"""
# TODO can we tell pypy that its never larger then 31-bit?
__slots__ = ('value',) # the only allowed slot here
- def __init__(self, value):
- self.value = value
-
def getclass(self, space):
"""Return SmallInteger from special objects array."""
return space.w_SmallInteger
Modified: pypy/branch/tagged-pointers-framework2/pypy/rlib/objectmodel.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rlib/objectmodel.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rlib/objectmodel.py Fri Oct 16 23:02:19 2009
@@ -359,7 +359,8 @@
class UnboxedValue(object):
"""A mixin class to use for classes that have exactly one field which
- is an integer. They are represented as a tagged pointer."""
+ is an integer. They are represented as a tagged pointer, if the
+ translation.taggedpointers config option is used."""
_mixin_ = True
def __new__(cls, value):
@@ -379,9 +380,9 @@
raise OverflowError("UnboxedValue: argument out of range")
def __repr__(self):
- return '<unboxed %d>' % (self.getvalue(),)
+ return '<unboxed %d>' % (self.get_untagged_value(),)
- def getvalue(self): # helper, equivalent to reading the custom field
+ def get_untagged_value(self): # helper, equivalent to reading the custom field
if isinstance(self.__class__.__slots__, str):
return getattr(self, self.__class__.__slots__)
else:
Modified: pypy/branch/tagged-pointers-framework2/pypy/rlib/test/test_objectmodel.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rlib/test/test_objectmodel.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rlib/test/test_objectmodel.py Fri Oct 16 23:02:19 2009
@@ -124,13 +124,13 @@
__slots__ = 'smallint'
assert C(17).smallint == 17
- assert C(17).getvalue() == 17
+ assert C(17).get_untagged_value() == 17
class A(UnboxedValue):
__slots__ = ['value']
assert A(12098).value == 12098
- assert A(12098).getvalue() == 12098
+ assert A(12098).get_untagged_value() == 12098
def test_symbolic():
py.test.skip("xxx no test here")
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/llmemory.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/llmemory.py Fri Oct 16 23:02:19 2009
@@ -464,8 +464,10 @@
return lltype.nullptr(EXPECTED_TYPE.TO)
def _cast_to_int(self):
+ # This is a bit annoying. We want this method to still work when the
+ # pointed-to object is dead
if self:
- return self.ptr._cast_to_int()
+ return self.ptr._cast_to_int(False)
else:
return 0
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/lltype.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/lltype.py Fri Oct 16 23:02:19 2009
@@ -816,6 +816,7 @@
if not ptr:
return nullptr(PTRTYPE.TO)
return opaqueptr(PTRTYPE.TO, 'hidden', container = ptr._obj,
+ ORIGTYPE = CURTYPE,
solid = ptr._solid)
elif (isinstance(CURTYPE.TO, OpaqueType)
and isinstance(PTRTYPE.TO, OpaqueType)):
@@ -899,7 +900,7 @@
top_parent = parent
return top_parent
-def normalizeptr(p):
+def normalizeptr(p, check=True):
# If p is a pointer, returns the same pointer casted to the largest
# containing structure (for the cast where p points to the header part).
# Also un-hides pointers to opaque. Null pointers become None.
@@ -907,12 +908,17 @@
T = typeOf(p)
if not isinstance(T, Ptr):
return p # primitive
- if not p:
+ obj = p._getobj(check)
+ if not obj:
return None # null pointer
if type(p._obj0) is int:
return p # a pointer obtained by cast_int_to_ptr
- container = p._obj._normalizedcontainer()
- if container is not p._obj:
+ container = obj._normalizedcontainer()
+ if type(container) is int:
+ # this must be an opaque ptr originating from an integer
+ assert isinstance(obj, _opaque)
+ return cast_int_to_ptr(obj.ORIGTYPE, container)
+ if container is not obj:
p = _ptr(Ptr(typeOf(container)), container, p._solid)
return p
@@ -1190,13 +1196,15 @@
raise RuntimeError("widening %r inside %r instead of %r" % (CURTYPE, PARENTTYPE, PTRTYPE.TO))
return _ptr(PTRTYPE, struc, solid=self._solid)
- def _cast_to_int(self):
- if not self:
+ def _cast_to_int(self, check=True):
+ obj = self._getobj(check)
+ if not obj:
return 0 # NULL pointer
- obj = self._obj
if isinstance(obj, int):
return obj # special case for cast_int_to_ptr() results
- obj = normalizeptr(self)._obj
+ obj = normalizeptr(self, check)._getobj(check)
+ if isinstance(obj, int):
+ return obj # special case for cast_int_to_ptr() results put into opaques
result = intmask(obj._getid())
# assume that id() returns an addressish value which is
# not zero and aligned to at least a multiple of 4
@@ -1739,6 +1747,9 @@
# if we are an opaque containing a normal Struct/GcStruct,
# unwrap it
if hasattr(self, 'container'):
+ # an integer, cast to a ptr, cast to an opaque
+ if type(self.container) is int:
+ return self.container
return self.container._normalizedcontainer()
else:
return _parentable._normalizedcontainer(self)
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/rtagged.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/rtagged.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/rtagged.py Fri Oct 16 23:02:19 2009
@@ -1,7 +1,7 @@
from pypy.objspace.flow.model import Constant
from pypy.rpython.rclass import getclassrepr, getinstancerepr, get_type_repr
from pypy.rpython.lltypesystem import lltype
-from pypy.rpython.lltypesystem.rclass import InstanceRepr, CLASSTYPE
+from pypy.rpython.lltypesystem.rclass import InstanceRepr, CLASSTYPE, ll_inst_type
from pypy.rpython.lltypesystem.rclass import MissingRTypeAttribute
from pypy.rpython.lltypesystem.rclass import ll_issubclass_const
from pypy.rpython.rmodel import TyperError, inputconst
@@ -53,7 +53,7 @@
def convert_const_exact(self, value):
self.setup()
- number = value.getvalue()
+ number = value.get_untagged_value()
return ll_int_to_unboxed(self.lowleveltype, number)
def getvalue_from_unboxed(self, llops, vinst):
@@ -62,7 +62,7 @@
c_one = inputconst(lltype.Signed, 1)
return llops.genop('int_rshift', [v2, c_one], resulttype=lltype.Signed)
- def gettype_from_unboxed(self, llops, vinst):
+ def gettype_from_unboxed(self, llops, vinst, can_be_none=False):
unboxedclass_repr = getclassrepr(self.rtyper, self.unboxedclassdef)
cunboxedcls = inputconst(CLASSTYPE, unboxedclass_repr.getvtable())
if self.is_parent:
@@ -81,8 +81,14 @@
vinst = llops.genop('cast_pointer', [vinst],
resulttype=self.common_repr())
if can_be_tagged:
- return llops.gendirectcall(ll_unboxed_getclass, vinst,
+ if can_be_none:
+ func = ll_unboxed_getclass_canbenone
+ else:
+ func = ll_unboxed_getclass
+ return llops.gendirectcall(func, vinst,
cunboxedcls)
+ elif can_be_none:
+ return llops.gendirectcall(ll_inst_type, vinst)
else:
ctypeptr = inputconst(lltype.Void, 'typeptr')
return llops.genop('getfield', [vinst, ctypeptr],
@@ -100,7 +106,8 @@
def rtype_type(self, hop):
[vinst] = hop.inputargs(self)
- return self.gettype_from_unboxed(hop.llops, vinst)
+ return self.gettype_from_unboxed(
+ hop.llops, vinst, can_be_none=hop.args_s[0].can_be_none())
def rtype_setattr(self, hop):
# only for UnboxedValue.__init__(), which is not actually called
@@ -141,11 +148,15 @@
def ll_unboxed_to_int(p):
return lltype.cast_ptr_to_int(p) >> 1
+def ll_unboxed_getclass_canbenone(instance, class_if_unboxed):
+ if instance:
+ return ll_unboxed_getclass(instance, class_if_unboxed)
+ return lltype.nullptr(lltype.typeOf(instance).TO.typeptr.TO)
+
def ll_unboxed_getclass(instance, class_if_unboxed):
if lltype.cast_ptr_to_int(instance) & 1:
return class_if_unboxed
- else:
- return instance.typeptr
+ return instance.typeptr
def ll_unboxed_isinstance_const(obj, minid, maxid, answer_if_unboxed):
if not obj:
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/test/test_rtagged.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/test/test_rtagged.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/lltypesystem/test/test_rtagged.py Fri Oct 16 23:02:19 2009
@@ -33,20 +33,20 @@
def test_instantiate():
def fn1(n):
return C(n)
- res = interpret(fn1, [42])
+ res = interpret(fn1, [42], taggedpointers=True)
value = lltype.cast_ptr_to_int(res)
assert value == 42 * 2 + 1 # for now
def test_attribute():
def fn1(n):
return C(n).smallint
- res = interpret(fn1, [42])
+ res = interpret(fn1, [42], taggedpointers=True)
assert res == 42
-def test_getvalue():
+def test_get_untagged_value():
def fn1(n):
- return C(n).getvalue()
- res = interpret(fn1, [42])
+ return C(n).get_untagged_value()
+ res = interpret(fn1, [42], taggedpointers=True)
assert res == 42
def test_overflowerror():
@@ -65,11 +65,11 @@
else:
return 'A', 0
- res = interpret(fn2, [-117])
+ res = interpret(fn2, [-117], taggedpointers=True)
assert res.item0 == 'C'
assert res.item1 == -117
- res = interpret(fn2, [sys.maxint])
+ res = interpret(fn2, [sys.maxint], taggedpointers=True)
assert res.item0 == 'B'
assert res.item1 == sys.maxint
@@ -95,13 +95,13 @@
else:
return 'A', 0
- res = interpret(fn, [12])
+ res = interpret(fn, [12], taggedpointers=True)
assert res.item0 == 'C'
assert res.item1 == 12
- res = interpret(fn, [-1])
+ res = interpret(fn, [-1], taggedpointers=True)
assert res.item0 == 'C'
assert res.item1 == 111
- res = interpret(fn, [0])
+ res = interpret(fn, [0], taggedpointers=True)
assert res.item0 == 'B'
assert res.item1 == 939393
@@ -118,9 +118,9 @@
x = C(n)
return g(x)
- res = interpret(fn, [-1])
+ res = interpret(fn, [-1], taggedpointers=True)
assert res == sys.maxint
- res = interpret(fn, [56])
+ res = interpret(fn, [56], taggedpointers=True)
assert res == 56
def test_type():
@@ -131,11 +131,32 @@
x = C(n)
return type(x) is B, type(x) is C
- res = interpret(fn, [-212])
+ res = interpret(fn, [-212], taggedpointers=True)
assert res.item0 and not res.item1
- res = interpret(fn, [9874])
+ res = interpret(fn, [9874], taggedpointers=True)
assert res.item1 and not res.item0
+def test_type_of_None():
+ # use extra function to prevent flow graph cleverness
+ def g(n):
+ if n < 0:
+ x = B(n)
+ elif n == 0:
+ x = None
+ else:
+ x = C(n)
+ return x
+ def fn(n):
+ x= g(n)
+ return type(x) is B, type(x) is C
+
+ res = interpret(fn, [-212], taggedpointers=True)
+ assert res.item0 and not res.item1
+ res = interpret(fn, [9874], taggedpointers=True)
+ assert res.item1 and not res.item0
+ res = interpret(fn, [0], taggedpointers=True)
+ assert not res.item1 and not res.item0
+
def test_str():
def fn(n):
if n > 0:
@@ -143,9 +164,9 @@
else:
x = C(n)
return str(x)
- res = interpret(fn, [-832])
+ res = interpret(fn, [-832], taggedpointers=True)
assert ''.join(res.chars) == '<unboxed -832>'
- res = interpret(fn, [1])
+ res = interpret(fn, [1], taggedpointers=True)
assert ''.join(res.chars).startswith('<B object')
def test_format():
@@ -155,9 +176,9 @@
else:
x = C(n)
return '%r' % (x,)
- res = interpret(fn, [-832])
+ res = interpret(fn, [-832], taggedpointers=True)
assert ''.join(res.chars) == '<unboxed -832>'
- res = interpret(fn, [1])
+ res = interpret(fn, [1], taggedpointers=True)
assert ''.join(res.chars).startswith('<B object')
def test_method():
@@ -167,9 +188,9 @@
else:
x = C(n)
return x.meth(100)
- res = interpret(fn, [1000])
+ res = interpret(fn, [1000], taggedpointers=True)
assert res == 1102
- res = interpret(fn, [-1000])
+ res = interpret(fn, [-1000], taggedpointers=True)
assert res == -897
def test_optimize_method():
@@ -179,7 +200,7 @@
else:
x = C(n)
return x.meth(100)
- interp, graph = get_interpreter(fn, [-1000])
+ interp, graph = get_interpreter(fn, [-1000], taggedpointers=True)
t = interp.typer.annotator.translator
t.config.translation.backendopt.constfold = True
@@ -206,7 +227,7 @@
x = D(5)
return g(x)
- interp, graph = get_interpreter(fn, [-1000])
+ interp, graph = get_interpreter(fn, [-1000], taggedpointers=True)
t = interp.typer.annotator.translator
ggraph = graphof(t, g)
@@ -216,3 +237,17 @@
assert res == 68
res = interp.eval_graph(graph, [3])
assert res == 66
+
+
+def test_disable_tagging():
+ def fn(n):
+ if n < 0:
+ x = B(n)
+ else:
+ x = C(n)
+ return type(x) is B, type(x) is C
+
+ res = interpret(fn, [-212], taggedpointers=False)
+ assert res.item0 and not res.item1
+ res = interpret(fn, [9874], taggedpointers=False)
+ assert res.item1 and not res.item0
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/base.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/base.py Fri Oct 16 23:02:19 2009
@@ -150,14 +150,17 @@
length = (obj + llmemory.gcarrayofptr_lengthoffset).signed[0]
item = obj + llmemory.gcarrayofptr_itemsoffset
while length > 0:
- callback(item, arg)
+ if self.points_to_valid_gc_object(item):
+ callback(item, arg)
item += llmemory.gcarrayofptr_singleitemoffset
length -= 1
return
offsets = self.offsets_to_gc_pointers(typeid)
i = 0
while i < len(offsets):
- callback(obj + offsets[i], arg)
+ item = obj + offsets[i]
+ if self.points_to_valid_gc_object(item):
+ callback(item, arg)
i += 1
if self.has_gcptr_in_varsize(typeid):
item = obj + self.varsize_offset_to_variable_part(typeid)
@@ -167,12 +170,22 @@
while length > 0:
j = 0
while j < len(offsets):
- callback(item + offsets[j], arg)
+ itemobj = item + offsets[j]
+ if self.points_to_valid_gc_object(itemobj):
+ callback(itemobj, arg)
j += 1
item += itemlength
length -= 1
trace._annspecialcase_ = 'specialize:arg(2)'
+ def points_to_valid_gc_object(self, addr):
+ return self.is_valid_gc_object(addr.address[0])
+
+ def is_valid_gc_object(self, addr):
+ return (addr != NULL and
+ (not self.config.taggedpointers or
+ llmemory.cast_adr_to_int(addr) & 1 == 0))
+
def debug_check_consistency(self):
"""To use after a collection. If self.DEBUG is set, this
enumerates all roots and traces all objects to check if we didn't
@@ -207,8 +220,8 @@
self._debug_record(obj)
def _debug_callback2(self, pointer, ignored):
obj = pointer.address[0]
- if obj:
- self._debug_record(obj)
+ ll_assert(bool(obj), "NULL address from self.trace()")
+ self._debug_record(obj)
def debug_check_object(self, obj):
pass
@@ -243,11 +256,17 @@
# Default implementation for id(), assuming that "external" objects
# never move. Overriden in the HybridGC.
obj = llmemory.cast_ptr_to_adr(ptr)
- if self._is_external(obj):
- result = obj
- else:
- result = self._compute_id(obj)
- return llmemory.cast_adr_to_int(result)
+
+ # is it a tagged pointer? or an external object?
+ if not self.is_valid_gc_object(obj) or self._is_external(obj):
+ return llmemory.cast_adr_to_int(obj)
+
+ # tagged pointers have ids of the form 2n + 1
+ # external objects have ids of the form 4n (due to word alignment)
+ # self._compute_id returns addresses of the form 2n + 1
+ # if we multiply by 2, we get ids of the form 4n + 2, thus we get no
+ # clashes
+ return llmemory.cast_adr_to_int(self._compute_id(obj)) * 2
def _next_id(self):
# return an id not currently in use (as an address instead of an int)
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/generation.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/generation.py Fri Oct 16 23:02:19 2009
@@ -132,6 +132,8 @@
return nursery_size // 4 - 1
def is_in_nursery(self, addr):
+ ll_assert(llmemory.cast_adr_to_int(addr) & 1 == 0,
+ "odd-valued (i.e. tagged) pointer unexpected here")
return self.nursery <= addr < self.nursery_top
def malloc_fixedsize_clear(self, typeid, size, can_collect,
@@ -305,10 +307,9 @@
def _trace_external_obj(self, pointer, obj):
addr = pointer.address[0]
- if addr != NULL:
- newaddr = self.copy(addr)
- pointer.address[0] = newaddr
- self.write_into_last_generation_obj(obj, newaddr)
+ newaddr = self.copy(addr)
+ pointer.address[0] = newaddr
+ self.write_into_last_generation_obj(obj, newaddr)
# ____________________________________________________________
# Implementation of nursery-only collections
@@ -446,10 +447,17 @@
# addr_struct, "<-", addr)
ll_assert(not self.is_in_nursery(addr_struct),
"nursery object with GCFLAG_NO_YOUNG_PTRS")
+ # if we have tagged pointers around, we first need to check whether
+ # we have valid pointer here, otherwise we can do it after the
+ # is_in_nursery check
+ if (self.config.taggedpointers and
+ not self.is_valid_gc_object(addr)):
+ return
if self.is_in_nursery(addr):
self.old_objects_pointing_to_young.append(addr_struct)
self.header(addr_struct).tid &= ~GCFLAG_NO_YOUNG_PTRS
- elif addr == NULL:
+ elif (not self.config.taggedpointers and
+ not self.is_valid_gc_object(addr)):
return
self.write_into_last_generation_obj(addr_struct, addr)
remember_young_pointer._dont_inline_ = True
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/hybrid.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/hybrid.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/hybrid.py Fri Oct 16 23:02:19 2009
@@ -567,6 +567,11 @@
def id(self, ptr):
obj = llmemory.cast_ptr_to_adr(ptr)
+
+ # is it a tagged pointer?
+ if not self.is_valid_gc_object(obj):
+ return llmemory.cast_adr_to_int(obj)
+
if self._is_external(obj):
# a prebuilt or rawmalloced object
if self.is_last_generation(obj):
@@ -581,7 +586,7 @@
result = obj
else:
result = self._compute_id(obj) # common case
- return llmemory.cast_adr_to_int(result)
+ return llmemory.cast_adr_to_int(result) * 2 # see comment in base.py
# XXX a possible optimization would be to use three dicts, one
# for each generation, instead of mixing gen2 and gen3 objects.
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/markcompact.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/markcompact.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/markcompact.py Fri Oct 16 23:02:19 2009
@@ -370,11 +370,10 @@
def _mark_obj(self, pointer, ignored):
obj = pointer.address[0]
- if obj != NULL:
- if self.marked(obj):
- return
- self.mark(obj)
- self.to_see.append(obj)
+ if self.marked(obj):
+ return
+ self.mark(obj)
+ self.to_see.append(obj)
def _mark_root_recursively(self, root):
self.mark(root.address[0])
@@ -437,14 +436,17 @@
length = (obj + llmemory.gcarrayofptr_lengthoffset).signed[0]
item = obj + llmemory.gcarrayofptr_itemsoffset
while length > 0:
- callback(item, arg)
+ if self.points_to_valid_gc_object(item):
+ callback(item, arg)
item += llmemory.gcarrayofptr_singleitemoffset
length -= 1
return
offsets = self.offsets_to_gc_pointers(typeid)
i = 0
while i < len(offsets):
- callback(obj + offsets[i], arg)
+ item = obj + offsets[i]
+ if self.points_to_valid_gc_object(item):
+ callback(item, arg)
i += 1
if self.has_gcptr_in_varsize(typeid):
item = obj + self.varsize_offset_to_variable_part(typeid)
@@ -454,7 +456,9 @@
while length > 0:
j = 0
while j < len(offsets):
- callback(item + offsets[j], arg)
+ itemobj = item + offsets[j]
+ if self.points_to_valid_gc_object(itemobj):
+ callback(itemobj, arg)
j += 1
item += itemlength
length -= 1
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/marksweep.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/marksweep.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/marksweep.py Fri Oct 16 23:02:19 2009
@@ -504,8 +504,7 @@
def _add_reachable(pointer, objects):
obj = pointer.address[0]
- if obj:
- objects.append(obj)
+ objects.append(obj)
_add_reachable = staticmethod(_add_reachable)
def statistics(self, index):
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/semispace.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gc/semispace.py Fri Oct 16 23:02:19 2009
@@ -370,8 +370,7 @@
self.trace(obj, self._trace_copy, None)
def _trace_copy(self, pointer, ignored):
- if pointer.address[0] != NULL:
- pointer.address[0] = self.copy(pointer.address[0])
+ pointer.address[0] = self.copy(pointer.address[0])
def surviving(self, obj):
# To use during a collection. Check if the object is currently
@@ -494,8 +493,7 @@
return scan
def _append_if_nonnull(pointer, stack):
- if pointer.address[0] != NULL:
- stack.append(pointer.address[0])
+ stack.append(pointer.address[0])
_append_if_nonnull = staticmethod(_append_if_nonnull)
def _finalization_state(self, obj):
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gctransform/asmgcroot.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gctransform/asmgcroot.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gctransform/asmgcroot.py Fri Oct 16 23:02:19 2009
@@ -254,7 +254,7 @@
if location == 0:
break
addr = self.getlocation(callee, location)
- if addr.address[0] != llmemory.NULL:
+ if gc.points_to_valid_gc_object(addr):
collect_stack_root(gc, addr)
#
# track where the caller_frame saved the registers from its own
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gctransform/framework.py Fri Oct 16 23:02:19 2009
@@ -1040,7 +1040,7 @@
end = gcdata.static_root_nongcend
while addr != end:
result = addr.address[0]
- if result.address[0] != llmemory.NULL:
+ if gc.points_to_valid_gc_object(result):
collect_static_in_prebuilt_nongc(gc, result)
addr += sizeofaddr
if collect_static_in_prebuilt_gc:
@@ -1048,7 +1048,7 @@
end = gcdata.static_root_end
while addr != end:
result = addr.address[0]
- if result.address[0] != llmemory.NULL:
+ if gc.points_to_valid_gc_object(result):
collect_static_in_prebuilt_gc(gc, result)
addr += sizeofaddr
if collect_stack_root:
@@ -1110,7 +1110,7 @@
addr = gcdata.root_stack_base
end = gcdata.root_stack_top
while addr != end:
- if addr.address[0] != llmemory.NULL:
+ if gc.points_to_valid_gc_object(addr):
collect_stack_root(gc, addr)
addr += sizeofaddr
if self.collect_stacks_from_other_threads is not None:
@@ -1219,7 +1219,7 @@
end = stacktop - sizeofaddr
addr = end.address[0]
while addr != end:
- if addr.address[0] != llmemory.NULL:
+ if gc.points_to_valid_gc_object(addr):
callback(gc, addr)
addr += sizeofaddr
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gcwrapper.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/gcwrapper.py Fri Oct 16 23:02:19 2009
@@ -144,15 +144,15 @@
gc = gcheap.gc
if collect_static_in_prebuilt_gc:
for addrofaddr in gcheap.constantroots:
- if addrofaddr.address[0]:
+ if self.gcheap.gc.points_to_valid_gc_object(addrofaddr):
collect_static_in_prebuilt_gc(gc, addrofaddr)
if collect_static_in_prebuilt_nongc:
for addrofaddr in gcheap.constantrootsnongc:
- if addrofaddr.address[0]:
+ if self.gcheap.gc.points_to_valid_gc_object(addrofaddr):
collect_static_in_prebuilt_nongc(gc, addrofaddr)
if collect_stack_root:
for addrofaddr in gcheap.llinterp.find_roots():
- if addrofaddr.address[0]:
+ if self.gcheap.gc.points_to_valid_gc_object(addrofaddr):
collect_stack_root(gc, addrofaddr)
def _walk_prebuilt_gc(self, collect): # debugging only! not RPython
@@ -208,7 +208,8 @@
def reccollect(constants, llvalue):
if (isinstance(llvalue, lltype._abstract_ptr)
- and llvalue._obj is not None and llvalue._obj not in constants):
+ and llvalue._obj is not None and llvalue._obj not in constants
+ and not isinstance(llvalue._obj, int)):
TYPE = llvalue._T
constants[llvalue._obj] = True
if isinstance(TYPE, lltype.Struct):
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/test/test_gc.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/test/test_gc.py Fri Oct 16 23:02:19 2009
@@ -10,6 +10,7 @@
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rlib.objectmodel import we_are_translated
from pypy.rlib.objectmodel import compute_unique_id, keepalive_until_here
+from pypy.rlib import rgc
def stdout_ignore_ll_functions(msg):
@@ -436,7 +437,6 @@
def test_can_move(self):
TP = lltype.GcArray(lltype.Float)
def func():
- from pypy.rlib import rgc
return rgc.can_move(lltype.malloc(TP, 1))
assert self.interpret(func, []) == self.GC_CAN_MOVE
@@ -444,7 +444,6 @@
def test_malloc_nonmovable(self):
TP = lltype.GcArray(lltype.Char)
def func():
- from pypy.rlib import rgc
a = rgc.malloc_nonmovable(TP, 3)
if a:
assert not rgc.can_move(a)
@@ -458,7 +457,6 @@
TP = lltype.GcStruct('T', ('s', lltype.Ptr(S)))
def func():
try:
- from pypy.rlib import rgc
a = rgc.malloc_nonmovable(TP)
rgc.collect()
if a:
@@ -473,7 +471,6 @@
def test_resizable_buffer(self):
from pypy.rpython.lltypesystem.rstr import STR
from pypy.rpython.annlowlevel import hlstr
- from pypy.rlib import rgc
def f():
ptr = rgc.resizable_buffer_of_shape(STR, 1)
@@ -484,6 +481,97 @@
assert self.interpret(f, []) == 2
+ def test_tagged_simple(self):
+ from pypy.rlib.objectmodel import UnboxedValue
+
+ class Unrelated(object):
+ pass
+
+ u = Unrelated()
+ u.x = UnboxedObject(47)
+ def fn(n):
+ rgc.collect() # check that a prebuilt tagged pointer doesn't explode
+ if n > 0:
+ x = BoxedObject(n)
+ else:
+ x = UnboxedObject(n)
+ u.x = x # invoke write barrier
+ rgc.collect()
+ return x.meth(100)
+ res = self.interpret(fn, [1000], taggedpointers=True)
+ assert res == 1102
+ res = self.interpret(fn, [-1000], taggedpointers=True)
+ assert res == -897
+
+ def test_tagged_prebuilt(self):
+
+ class F:
+ pass
+
+ f = F()
+ f.l = [UnboxedObject(10)]
+ def fn(n):
+ if n > 0:
+ x = BoxedObject(n)
+ else:
+ x = UnboxedObject(n)
+ f.l.append(x)
+ rgc.collect()
+ return f.l[-1].meth(100)
+ res = self.interpret(fn, [1000], taggedpointers=True)
+ assert res == 1102
+ res = self.interpret(fn, [-1000], taggedpointers=True)
+ assert res == -897
+
+ def test_tagged_id(self):
+ from pypy.rlib.objectmodel import UnboxedValue, compute_unique_id
+
+ class Unrelated(object):
+ pass
+
+ u = Unrelated()
+ u.x = UnboxedObject(0)
+ def fn(n):
+ id_prebuilt1 = compute_unique_id(u.x)
+ if n > 0:
+ x = BoxedObject(n)
+ else:
+ x = UnboxedObject(n)
+ id_x1 = compute_unique_id(x)
+ rgc.collect() # check that a prebuilt tagged pointer doesn't explode
+ id_prebuilt2 = compute_unique_id(u.x)
+ id_x2 = compute_unique_id(x)
+ print u.x, id_prebuilt1, id_prebuilt2
+ print x, id_x1, id_x2
+ return ((id_x1 == id_x2) * 1 +
+ (id_prebuilt1 == id_prebuilt2) * 10 +
+ (id_x1 != id_prebuilt1) * 100)
+ res = self.interpret(fn, [1000], taggedpointers=True)
+ assert res == 111
+ res = self.interpret(fn, [-1000], taggedpointers=True)
+ assert res == 111
+
+
+from pypy.rlib.objectmodel import UnboxedValue
+
+class TaggedBase(object):
+ __slots__ = ()
+ def meth(self, x):
+ raise NotImplementedError
+
+class BoxedObject(TaggedBase):
+ attrvalue = 66
+ def __init__(self, normalint):
+ self.normalint = normalint
+ def meth(self, x):
+ return self.normalint + x + 2
+
+class UnboxedObject(TaggedBase, UnboxedValue):
+ __slots__ = 'smallint'
+ def meth(self, x):
+ return self.smallint + x + 3
+
+
class TestMarkSweepGC(GCTest):
from pypy.rpython.memory.gc.marksweep import MarkSweepGC as GCClass
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/test/test_transformed_gc.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/memory/test/test_transformed_gc.py Fri Oct 16 23:02:19 2009
@@ -9,6 +9,7 @@
from pypy.rpython.memory.gc.marksweep import X_CLONE, X_POOL, X_POOL_PTR
from pypy.rlib.objectmodel import compute_unique_id, we_are_translated
from pypy.rlib.debug import ll_assert
+from pypy.rlib import rgc
from pypy import conftest
from pypy.rlib.rstring import StringBuilder
@@ -470,7 +471,6 @@
def test_can_move(self):
TP = lltype.GcArray(lltype.Float)
def func():
- from pypy.rlib import rgc
return rgc.can_move(lltype.malloc(TP, 1))
run = self.runner(func)
res = run([])
@@ -480,7 +480,6 @@
TP = lltype.GcArray(lltype.Char)
def func():
#try:
- from pypy.rlib import rgc
a = rgc.malloc_nonmovable(TP, 3)
rgc.collect()
if a:
@@ -498,7 +497,6 @@
TP = lltype.GcStruct('T', ('s', lltype.Ptr(S)))
def func():
try:
- from pypy.rlib import rgc
a = rgc.malloc_nonmovable(TP)
rgc.collect()
if a:
@@ -514,7 +512,6 @@
def test_resizable_buffer(self):
from pypy.rpython.lltypesystem.rstr import STR
from pypy.rpython.annlowlevel import hlstr
- from pypy.rlib import rgc
def f():
ptr = rgc.resizable_buffer_of_shape(STR, 2)
@@ -543,6 +540,68 @@
res = fn([])
assert res == 'y'
+ def test_tagged_simple(self):
+ class Unrelated(object):
+ pass
+
+ u = Unrelated()
+ u.x = UnboxedObject(47)
+ def fn(n):
+ rgc.collect() # check that a prebuilt tagged pointer doesn't explode
+ if n > 0:
+ x = BoxedObject(n)
+ else:
+ x = UnboxedObject(n)
+ u.x = x # invoke write barrier
+ rgc.collect()
+ return x.meth(100)
+ def func():
+ return fn(1000) + fn(-1000)
+ func = self.runner(func, taggedpointers=True)
+ res = func([])
+ assert res == fn(1000) + fn(-1000)
+
+ def test_tagged_prebuilt(self):
+
+ class F:
+ pass
+
+ f = F()
+ f.l = [UnboxedObject(10)]
+ def fn(n):
+ if n > 0:
+ x = BoxedObject(n)
+ else:
+ x = UnboxedObject(n)
+ f.l.append(x)
+ rgc.collect()
+ return f.l[-1].meth(100)
+ def func():
+ return fn(1000) ^ fn(-1000)
+ func = self.runner(func, taggedpointers=True)
+ res = func([])
+ assert res == fn(1000) ^ fn(-1000)
+
+from pypy.rlib.objectmodel import UnboxedValue
+
+class TaggedBase(object):
+ __slots__ = ()
+ def meth(self, x):
+ raise NotImplementedError
+
+class BoxedObject(TaggedBase):
+ attrvalue = 66
+ def __init__(self, normalint):
+ self.normalint = normalint
+ def meth(self, x):
+ return self.normalint + x + 2
+
+class UnboxedObject(TaggedBase, UnboxedValue):
+ __slots__ = 'smallint'
+ def meth(self, x):
+ return self.smallint + x + 3
+
+
class GenericMovingGCTests(GenericGCTests):
GC_CAN_MOVE = True
GC_CANNOT_MALLOC_NONMOVABLE = True
@@ -736,7 +795,6 @@
assert res == 22220221
def test_cloning_highlevel(self):
- from pypy.rlib import rgc
class A:
pass
class B(A):
@@ -770,7 +828,6 @@
assert res == 1
def test_cloning_highlevel_varsize(self):
- from pypy.rlib import rgc
class A:
pass
def func(n, dummy):
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/rclass.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/rclass.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/rclass.py Fri Oct 16 23:02:19 2009
@@ -56,11 +56,14 @@
issubclass(subdef.classdesc.pyobj, UnboxedValue)]
virtualizable2 = classdef.classdesc.read_attribute('_virtualizable2_',
Constant(False)).value
+ config = rtyper.annotator.translator.config
+ usetagging = len(unboxed) != 0 and config.translation.taggedpointers
+
if virtualizable2:
assert len(unboxed) == 0
assert gcflavor == 'gc'
return rtyper.type_system.rvirtualizable2.Virtualizable2InstanceRepr(rtyper, classdef)
- elif len(unboxed) > 0 and rtyper.type_system.name == 'lltypesystem':
+ elif usetagging and rtyper.type_system.name == 'lltypesystem':
# the UnboxedValue class and its parent classes need a
# special repr for their instances
if len(unboxed) != 1:
Modified: pypy/branch/tagged-pointers-framework2/pypy/rpython/test/test_rptr.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/rpython/test/test_rptr.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/rpython/test/test_rptr.py Fri Oct 16 23:02:19 2009
@@ -112,6 +112,20 @@
interpret(fn, [11521])
+def test_odd_ints_opaque():
+ T = GcStruct('T')
+ Q = GcOpaqueType('Q')
+ PT = Ptr(T)
+ PQ = Ptr(Q)
+ def fn(n):
+ t = cast_int_to_ptr(PT, n)
+ assert typeOf(t) == PT
+ assert cast_ptr_to_int(t) == n
+ o = cast_opaque_ptr(PQ, t)
+ assert cast_ptr_to_int(o) == n
+
+ fn(13)
+ interpret(fn, [11521])
def test_Ptr():
S = GcStruct('s')
Modified: pypy/branch/tagged-pointers-framework2/pypy/translator/c/gcc/test/test_asmgcroot.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/translator/c/gcc/test/test_asmgcroot.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/translator/c/gcc/test/test_asmgcroot.py Fri Oct 16 23:02:19 2009
@@ -159,3 +159,8 @@
def define_callback_with_collect(cls):
return lambda: 0
+
+
+class TestAsmGCRootWithHybridTagged(AbstractTestAsmGCRoot,
+ test_newgc.TestHybridTaggedPointers):
+ pass
Modified: pypy/branch/tagged-pointers-framework2/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/translator/c/test/test_newgc.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/translator/c/test/test_newgc.py Fri Oct 16 23:02:19 2009
@@ -17,6 +17,7 @@
gcpolicy = "marksweep"
should_be_moving = False
removetypeptr = False
+ taggedpointers = False
GC_CAN_MOVE = False
GC_CANNOT_MALLOC_NONMOVABLE = False
@@ -25,9 +26,10 @@
@classmethod
def _makefunc2(cls, f):
t = Translation(f, [int, int], gc=cls.gcpolicy,
- policy=annpolicy.StrictAnnotatorPolicy())
- t.config.translation.gcconfig.debugprint = True
- t.config.translation.gcconfig.removetypeptr = cls.removetypeptr
+ policy=annpolicy.StrictAnnotatorPolicy(),
+ taggedpointers=cls.taggedpointers,
+ removetypeptr=cls.removetypeptr,
+ debugprint=True)
t.disable(['backendopt'])
t.set_backend_extra_options(c_isolated=True, c_debug_defines=True)
t.rtype()
@@ -660,7 +662,6 @@
TP = lltype.GcArray(lltype.Char)
def func():
try:
- from pypy.rlib import rgc
a = rgc.malloc_nonmovable(TP, 3)
rgc.collect()
if a:
@@ -925,9 +926,12 @@
def test_gc_set_max_heap_size(self):
py.test.skip("not implemented")
+
+
class TestHybridGCRemoveTypePtr(TestHybridGC):
removetypeptr = True
+
class TestMarkCompactGC(TestSemiSpaceGC):
gcpolicy = "markcompact"
should_be_moving = True
@@ -940,3 +944,52 @@
def test_finalizer_order(self):
py.test.skip("not implemented")
+
+# ____________________________________________________________________
+
+class TestHybridTaggedPointers(TestHybridGC):
+ taggedpointers = True
+
+
+ def define_tagged(cls):
+ class Unrelated(object):
+ pass
+
+ u = Unrelated()
+ u.x = UnboxedObject(47)
+ def fn(n):
+ rgc.collect() # check that a prebuilt tagged pointer doesn't explode
+ if n > 0:
+ x = BoxedObject(n)
+ else:
+ x = UnboxedObject(n)
+ u.x = x # invoke write barrier
+ rgc.collect()
+ return x.meth(100)
+ def func():
+ return fn(1000) + fn(-1000)
+ return func
+
+ def test_tagged(self):
+ expected = self.run_orig("tagged")
+ res = self.run("tagged")
+ assert res == expected
+
+from pypy.rlib.objectmodel import UnboxedValue
+
+class TaggedBase(object):
+ __slots__ = ()
+ def meth(self, x):
+ raise NotImplementedError
+
+class BoxedObject(TaggedBase):
+ attrvalue = 66
+ def __init__(self, normalint):
+ self.normalint = normalint
+ def meth(self, x):
+ return self.normalint + x + 2
+
+class UnboxedObject(TaggedBase, UnboxedValue):
+ __slots__ = 'smallint'
+ def meth(self, x):
+ return self.smallint + x + 3
Modified: pypy/branch/tagged-pointers-framework2/pypy/translator/c/test/test_rtagged.py
==============================================================================
--- pypy/branch/tagged-pointers-framework2/pypy/translator/c/test/test_rtagged.py (original)
+++ pypy/branch/tagged-pointers-framework2/pypy/translator/c/test/test_rtagged.py Fri Oct 16 23:02:19 2009
@@ -38,7 +38,7 @@
def entry_point(argv):
n = 100 + len(argv)
- assert C(n).getvalue() == n
+ assert C(n).get_untagged_value() == n
x = makeint(42)
assert isinstance(x, C)
@@ -67,7 +67,7 @@
from pypy import conftest
def test_tagged_boehm():
- t = Translation(entry_point, standalone=True, gc='boehm')
+ t = Translation(entry_point, standalone=True, gc='boehm', taggedpointers=True)
try:
exename = str(t.compile_c())
finally:
More information about the Pypy-commit
mailing list