[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