[pypy-svn] r72490 - in pypy/trunk/pypy: rpython/lltypesystem rpython/memory/gc rpython/memory/gctransform translator/c translator/c/src

arigo at codespeak.net arigo at codespeak.net
Sun Mar 21 12:20:06 CET 2010


Author: arigo
Date: Sun Mar 21 12:20:04 2010
New Revision: 72490

Modified:
   pypy/trunk/pypy/rpython/lltypesystem/llgroup.py
   pypy/trunk/pypy/rpython/memory/gc/markcompact.py
   pypy/trunk/pypy/rpython/memory/gc/marksweep.py
   pypy/trunk/pypy/rpython/memory/gc/semispace.py
   pypy/trunk/pypy/rpython/memory/gctransform/framework.py
   pypy/trunk/pypy/translator/c/node.py
   pypy/trunk/pypy/translator/c/primitive.py
   pypy/trunk/pypy/translator/c/src/llgroup.h
Log:
Change the CombinedSymbolics on 64-bit machines: they are now two
32-bit halves, instead of a USHORT and the rest.  This allows a
simpler and (likely) faster implementation of llgroup.h, where
instead of this complex 16-bit number we just store the pointer
in the lower 32 bits.  This should work everywhere because the
pointers are always to static data, and so they probably always
fit in a 32-bit field.  (This is checked, of course.)


Modified: pypy/trunk/pypy/rpython/lltypesystem/llgroup.py
==============================================================================
--- pypy/trunk/pypy/rpython/lltypesystem/llgroup.py	(original)
+++ pypy/trunk/pypy/rpython/lltypesystem/llgroup.py	Sun Mar 21 12:20:04 2010
@@ -1,13 +1,19 @@
 import weakref
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+from pypy.rlib.rarithmetic import LONG_BIT
 
 
 class GroupType(lltype.ContainerType):
     """A 'group' that stores static structs together in memory.
-    The point is that they can be referenced by a GroupMemberOffset
-    which only takes 2 bytes (a USHORT), so the total size of a group
-    is limited to 18 or 19 bits (= the 16 bits in a USHORT, plus 2 or
-    3 bits at the end that are zero and so don't need to be stored).
+
+    On 32-bit platforms, the point is that they can be referenced by a
+    GroupMemberOffset which only takes 2 bytes (a USHORT), so the total
+    size of a group is limited to 18 (= the 16 bits in a USHORT, plus 2
+    bits at the end that are zero and so don't need to be stored).
+
+    On 64-bit platforms, we check that the address they end up at is
+    within the first 32 bits, so that we can store that address in half
+    a long (i.e. in a UINT).
     """
     _gckind = 'raw'
 
@@ -43,16 +49,24 @@
 _membership = weakref.WeakValueDictionary()
 
 
+if LONG_BIT == 32:
+    HALFWORD = rffi.USHORT
+    r_halfword = rffi.r_ushort
+else:
+    HALFWORD = rffi.UINT
+    r_halfword = rffi.r_uint
+
+
 class GroupMemberOffset(llmemory.Symbolic):
-    """The offset of a struct inside a group, stored compactly in a USHORT.
-    Can only be used by the lloperation 'get_group_member'.
+    """The offset of a struct inside a group, stored compactly in a HALFWORD
+    (a USHORT or UINT). Can only be used by the lloperation 'get_group_member'.
     """
     def annotation(self):
         from pypy.annotation import model
-        return model.SomeInteger(knowntype=rffi.r_ushort)
+        return model.SomeInteger(knowntype=r_halfword)
 
     def lltype(self):
-        return rffi.USHORT
+        return HALFWORD
 
     def __init__(self, grp, memberindex):
         assert lltype.typeOf(grp) == Group
@@ -76,11 +90,15 @@
 
 
 class CombinedSymbolic(llmemory.Symbolic):
-    """A general-purpose Signed symbolic that combines a USHORT and the
-    rest of the word (typically flags).  Only supports extracting the USHORT
+    """A general-purpose Signed symbolic that combines an unsigned half-word
+    (USHORT on 32-bit platforms, UINT on 64-bit platforms) and the rest
+    of the word (typically flags).  Only supports extracting the half-word
     with 'llop.extract_ushort', and extracting the rest of the word with
-    '&~0xFFFF' or with a direct masking like '&0x10000'.
+    '&~0xFFFF' or with a direct masking like '&0x10000' (resp. on 64-bit
+    platform, with '&~0xFFFFFFFF' or '&0x100000000').
     """
+    MASK = (1<<(LONG_BIT//2))-1     # 0xFFFF or 0xFFFFFFFF
+
     def annotation(self):
         from pypy.annotation import model
         return model.SomeInteger()
@@ -89,7 +107,7 @@
         return lltype.Signed
 
     def __init__(self, lowpart, rest):
-        assert (rest & 0xFFFF) == 0
+        assert (rest & CombinedSymbolic.MASK) == 0
         self.lowpart = lowpart
         self.rest = rest
 
@@ -97,22 +115,22 @@
         return '<CombinedSymbolic %r|%s>' % (self.lowpart, self.rest)
 
     def __and__(self, other):
-        if (other & 0xFFFF) == 0:
+        if (other & CombinedSymbolic.MASK) == 0:
             return self.rest & other
-        if (other & 0xFFFF) == 0xFFFF:
+        if (other & CombinedSymbolic.MASK) == CombinedSymbolic.MASK:
             return CombinedSymbolic(self.lowpart, self.rest & other)
         raise Exception("other=0x%x" % other)
 
     def __or__(self, other):
-        assert (other & 0xFFFF) == 0
+        assert (other & CombinedSymbolic.MASK) == 0
         return CombinedSymbolic(self.lowpart, self.rest | other)
 
     def __add__(self, other):
-        assert (other & 0xFFFF) == 0
+        assert (other & CombinedSymbolic.MASK) == 0
         return CombinedSymbolic(self.lowpart, self.rest + other)
 
     def __sub__(self, other):
-        assert (other & 0xFFFF) == 0
+        assert (other & CombinedSymbolic.MASK) == 0
         return CombinedSymbolic(self.lowpart, self.rest - other)
 
     def __eq__(self, other):

Modified: pypy/trunk/pypy/rpython/memory/gc/markcompact.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gc/markcompact.py	(original)
+++ pypy/trunk/pypy/rpython/memory/gc/markcompact.py	Sun Mar 21 12:20:04 2010
@@ -66,7 +66,7 @@
 # XXX adjust
 GC_CLEARANCE = 32*1024
 
-TID_TYPE = rffi.USHORT
+TID_TYPE = llgroup.HALFWORD
 BYTES_PER_TID = rffi.sizeof(TID_TYPE)
 
 
@@ -354,7 +354,7 @@
 
     def get_type_id(self, addr):
         tid = self.header(addr).tid
-        return llop.extract_ushort(rffi.USHORT, tid)
+        return llop.extract_ushort(llgroup.HALFWORD, tid)
 
     def mark_roots_recursively(self):
         self.root_walker.walk_roots(

Modified: pypy/trunk/pypy/rpython/memory/gc/marksweep.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gc/marksweep.py	(original)
+++ pypy/trunk/pypy/rpython/memory/gc/marksweep.py	Sun Mar 21 12:20:04 2010
@@ -4,7 +4,7 @@
 from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE
 from pypy.rpython.memory.support import get_address_stack
 from pypy.rpython.memory.gcheader import GCHeaderBuilder
-from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi, llgroup
 from pypy.rlib.objectmodel import free_non_gc_object
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rlib.rarithmetic import ovfcheck
@@ -29,7 +29,7 @@
     HDRPTR = lltype.Ptr(HDR)
     # need to maintain a linked list of malloced objects, since we used the
     # systems allocator and can't walk the heap
-    HDR.become(lltype.Struct('header', ('typeid16', rffi.USHORT),
+    HDR.become(lltype.Struct('header', ('typeid16', llgroup.HALFWORD),
                                        ('mark', lltype.Bool),
                                        ('flags', lltype.Char),
                                        ('next', HDRPTR)))

Modified: pypy/trunk/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gc/semispace.py	(original)
+++ pypy/trunk/pypy/rpython/memory/gc/semispace.py	Sun Mar 21 12:20:04 2010
@@ -4,18 +4,18 @@
 from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE
 from pypy.rpython.memory.support import get_address_stack, get_address_deque
 from pypy.rpython.memory.support import AddressDict
-from pypy.rpython.lltypesystem import lltype, llmemory, llarena, rffi
+from pypy.rpython.lltypesystem import lltype, llmemory, llarena, rffi, llgroup
 from pypy.rlib.objectmodel import free_non_gc_object
 from pypy.rlib.debug import ll_assert, have_debug_prints
 from pypy.rlib.debug import debug_print, debug_start, debug_stop
 from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.rlib.rarithmetic import ovfcheck
+from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT
 from pypy.rpython.memory.gc.base import MovingGCBase, ARRAY_TYPEID_MAP,\
      TYPEID_MAP
 
 import sys, os
 
-first_gcflag = 1 << 16
+first_gcflag = 1 << (LONG_BIT//2)
 GCFLAG_FORWARDED = first_gcflag
 # GCFLAG_EXTERNAL is set on objects not living in the semispace:
 # either immortal objects or (for HybridGC) externally raw_malloc'ed
@@ -458,7 +458,7 @@
         # Although calling get_type_id() on a forwarded object works by itself,
         # we catch it as an error because it's likely that what is then
         # done with the typeid is bogus.
-        return llop.extract_ushort(rffi.USHORT, tid)
+        return llop.extract_ushort(llgroup.HALFWORD, tid)
 
     def init_gc_object(self, addr, typeid16, flags=0):
         hdr = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.HDR))

Modified: pypy/trunk/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/trunk/pypy/rpython/memory/gctransform/framework.py	Sun Mar 21 12:20:04 2010
@@ -1,7 +1,7 @@
 from pypy.rpython.memory.gctransform.transform import GCTransformer
 from pypy.rpython.memory.gctransform.support import find_gc_ptrs_in_type, \
      get_rtti, ll_call_destructor, type_contains_pyobjs, var_ispyobj
-from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi, llgroup
 from pypy.rpython import rmodel
 from pypy.rpython.memory import gctypelayout
 from pypy.rpython.memory.gc import marksweep
@@ -22,7 +22,7 @@
 import sys, types
 
 
-TYPE_ID = rffi.USHORT
+TYPE_ID = llgroup.HALFWORD
 
 class CollectAnalyzer(graphanalyze.BoolGraphAnalyzer):
 
@@ -302,7 +302,7 @@
                     minimal_transform=False)
             self.get_member_index_ptr = getfn(
                 GCClass.get_member_index.im_func,
-                [s_gc, annmodel.SomeInteger(knowntype=rffi.r_ushort)],
+                [s_gc, annmodel.SomeInteger(knowntype=llgroup.r_halfword)],
                 annmodel.SomeInteger())
 
         if hasattr(GCClass, 'writebarrier_before_copy'):

Modified: pypy/trunk/pypy/translator/c/node.py
==============================================================================
--- pypy/trunk/pypy/translator/c/node.py	(original)
+++ pypy/trunk/pypy/translator/c/node.py	Sun Mar 21 12:20:04 2010
@@ -989,13 +989,18 @@
             forward_cdecl(ctype, self.name, self.db.standalone,
                           self.is_thread_local()))
         yield '#include "src/llgroup.h"'
-        yield 'PYPY_GROUP_CHECK_SIZE(%s);' % self.name
         for i, member in enumerate(self.obj.members):
             structnode = self.db.getcontainernode(member)
             yield '#define %s %s.member%d' % (structnode.name,
                                               self.name, i)
         yield ''
 
+    def startupcode(self):
+        count = len(self.obj.members)
+        if count == 0:
+            return []
+        return ['PYPY_GROUP_CHECK_SIZE(%s, member%d);' % (self.name, count-1)]
+
     def initializationexpr(self):
         self._fix_members()
         lines = ['{']

Modified: pypy/trunk/pypy/translator/c/primitive.py
==============================================================================
--- pypy/trunk/pypy/translator/c/primitive.py	(original)
+++ pypy/trunk/pypy/translator/c/primitive.py	Sun Mar 21 12:20:04 2010
@@ -58,7 +58,9 @@
         elif isinstance(value, ComputedIntSymbolic):
             value = value.compute_fn()
         elif isinstance(value, llgroup.CombinedSymbolic):
-            return '(%s|%dL)' % (name_ushort(value.lowpart, db), value.rest)
+            name = name_small_integer(value.lowpart, db)
+            assert (value.rest & value.MASK) == 0
+            return '(%s+%dL)' % (name, value.rest)
         else:
             raise Exception("unimplemented symbolic %r"%value)
     if value is None:
@@ -139,12 +141,14 @@
     else:
         return 'NULL'
 
-def name_ushort(value, db):
+def name_small_integer(value, db):
+    """Works for integers of size at most INT or UINT."""
     if isinstance(value, Symbolic):
         if isinstance(value, llgroup.GroupMemberOffset):
             groupnode = db.getcontainernode(value.grpptr._as_obj())
-            return 'GROUP_MEMBER_OFFSET(%s, member%s)' % (
+            return 'GROUP_MEMBER_OFFSET(%s, %s, member%s)' % (
                 cdecl(groupnode.implementationtypename, ''),
+                groupnode.name,
                 value.index,
                 )
         else:
@@ -166,7 +170,6 @@
     Void:     name_void,
     Address:  name_address,
     GCREF:    name_gcref,
-    rffi.USHORT: name_ushort,
     }
 
 PrimitiveType = {
@@ -182,27 +185,25 @@
     Void:     'void @',
     Address:  'void* @',
     GCREF:    'void* @',
-    rffi.USHORT: 'unsigned short @',
     }
 
-def define_c_primitive(ll_type, c_name):
+def define_c_primitive(ll_type, c_name, suffix=''):
     if ll_type in PrimitiveName:
         return
-    if ll_type._cast(-1) > 0:
-        name_str = '((%s) %%dULL)' % c_name
+    if suffix == '':
+        PrimitiveName[ll_type] = name_small_integer
     else:
-        name_str = '((%s) %%dLL)' % c_name
-    PrimitiveName[ll_type] = lambda value, db: name_str % value
+        name_str = '((%s) %%d%s)' % (c_name, suffix)
+        PrimitiveName[ll_type] = lambda value, db: name_str % value
     PrimitiveType[ll_type] = '%s @'% c_name
-    
-for ll_type, c_name in [(rffi.SIGNEDCHAR, 'signed char'),
-                        (rffi.UCHAR, 'unsigned char'),
-                        (rffi.SHORT, 'short'),
-                        #(rffi.USHORT, 'unsigned short'),
-                        (rffi.INT, 'int'),
-                        (rffi.UINT, 'unsigned int'),
-                        (rffi.LONG, 'long'),
-                        (rffi.ULONG, 'unsigned long'),
-                        (rffi.LONGLONG, 'long long'),
-                        (rffi.ULONGLONG, 'unsigned long long')]:
-    define_c_primitive(ll_type, c_name)
+
+define_c_primitive(rffi.SIGNEDCHAR, 'signed char')
+define_c_primitive(rffi.UCHAR, 'unsigned char')
+define_c_primitive(rffi.SHORT, 'short')
+define_c_primitive(rffi.USHORT, 'unsigned short')
+define_c_primitive(rffi.INT, 'int')
+define_c_primitive(rffi.UINT, 'unsigned int')
+define_c_primitive(rffi.LONG, 'long', 'L')
+define_c_primitive(rffi.ULONG, 'unsigned long', 'UL')
+define_c_primitive(rffi.LONGLONG, 'long long', 'LL')
+define_c_primitive(rffi.ULONGLONG, 'unsigned long long', 'ULL')

Modified: pypy/trunk/pypy/translator/c/src/llgroup.h
==============================================================================
--- pypy/trunk/pypy/translator/c/src/llgroup.h	(original)
+++ pypy/trunk/pypy/translator/c/src/llgroup.h	Sun Mar 21 12:20:04 2010
@@ -1,29 +1,63 @@
 #ifndef _PYPY_LL_GROUP_H_
 #define _PYPY_LL_GROUP_H_
 
-#define GROUP_MEMBER_OFFSET(grouptype, membername)  \
-  ((unsigned short)(((int)&((grouptype*)NULL)->membername) / sizeof(long)))
+/* Support code for CombinedSymbolics */
+
+
+#if PYPY_LONG_BIT == 32 /************************************/
+/* On 32-bit platforms, a CombinedSymbolic is two USHORTs, and the
+   lower one stores the offset inside the group, divided by 4.  The
+   limitation is to have at most 256KB of data in the whole group. */
+
+#define GROUP_MEMBER_OFFSET(grouptype, groupname, membername)           \
+  ((unsigned short)(((long)&((grouptype*)NULL)->membername) / 4))
+
+#define _OP_GET_GROUP_MEMBER(groupptr, compactoffset)  \
+  (((char*)groupptr) + ((long)compactoffset)*4)
+
+#define _OP_GET_NEXT_GROUP_MEMBER(groupptr, compactoffset, skipoffset)  \
+  ((((char*)groupptr) + skipoffset) + ((long)compactoffset)*4)
+
+#define OP_IS_GROUP_MEMBER_NONZERO(compactoffset, r)  \
+  r = (compactoffset != 0)
+
+#define OP_EXTRACT_USHORT(value, r)         r = (unsigned short)value
+#define OP_COMBINE_USHORT(ushort, rest, r)  r = ((long)ushort) | rest
+
+/* A macro to check at run-time if sizeof(group) is too large. */
+#define PYPY_GROUP_CHECK_SIZE(groupname, lastname)   \
+  if (sizeof(groupname) > 65536*4)  \
+    error = "group " #groupname " is more than 256KB of data"
+
+
+#else /******************************************************/
+/* On 64-bit platforms, a CombinedSymbolic is two UINTs, and the lower
+   one stores a real pointer to the group memeber.  The limitation is
+   that this pointer must fit inside 32-bit, i.e. the whole group must
+   be located in the first 32 bits of address space. */
+
+#define GROUP_MEMBER_OFFSET(grouptype, groupname, membername)   \
+  ((long)(&groupname.membername))
 
 #define _OP_GET_GROUP_MEMBER(groupptr, compactoffset)  \
-  (((char*)groupptr) + ((long)compactoffset)*sizeof(long))
+  ((long)compactoffset)
 
 #define _OP_GET_NEXT_GROUP_MEMBER(groupptr, compactoffset, skipoffset)  \
-  ((((char*)groupptr) + skipoffset) + ((long)compactoffset)*sizeof(long))
+  ((long)compactoffset + skipoffset)
 
 #define OP_IS_GROUP_MEMBER_NONZERO(compactoffset, r)  \
   r = (compactoffset != 0)
 
-#define OP_EXTRACT_USHORT(value, r)  \
-  r = (unsigned short)value
+#define OP_EXTRACT_USHORT(value, r)         r = (unsigned int)value
+#define OP_COMBINE_USHORT(ushort, rest, r)  r = ((long)ushort) | rest
 
-#define OP_COMBINE_USHORT(ushort, rest, r)  \
-  r = ((long)ushort) | rest;
+/* A macro to check at run-time if the group is below the 32-bit limit. */
+#define PYPY_GROUP_CHECK_SIZE(groupname, lastname)          \
+  if ((unsigned long)(&groupname.lastname) > 0xFFFFFFFF)    \
+    error = "group " #groupname " is not located in the "   \
+            "initial 32 bits of address space"
 
-/* A macro to crash at compile-time if sizeof(group) is too large.
-   Uses a hack that I've found on some random forum.  Haaaaaaaaaackish. */
-#define PYPY_GROUP_CHECK_SIZE(groupname)                              \
-  typedef char group_##groupname##_is_too_large[2*(sizeof(groupname)  \
-                                                   <= 65536 * sizeof(long))-1]
 
+#endif /*****************************************************/
 
 #endif /* _PYPY_LL_GROUP_H_ */



More information about the Pypy-commit mailing list