[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