[pypy-svn] r68393 - in pypy/branch/gc-hash/pypy: rpython/lltypesystem rpython/memory/gc rpython/memory/gctransform translator/c translator/c/test
arigo at codespeak.net
arigo at codespeak.net
Tue Oct 13 20:15:53 CEST 2009
Author: arigo
Date: Tue Oct 13 20:15:53 2009
New Revision: 68393
Modified:
pypy/branch/gc-hash/pypy/rpython/lltypesystem/lloperation.py
pypy/branch/gc-hash/pypy/rpython/memory/gc/base.py
pypy/branch/gc-hash/pypy/rpython/memory/gc/marksweep.py
pypy/branch/gc-hash/pypy/rpython/memory/gctransform/framework.py
pypy/branch/gc-hash/pypy/translator/c/database.py
pypy/branch/gc-hash/pypy/translator/c/gc.py
pypy/branch/gc-hash/pypy/translator/c/node.py
pypy/branch/gc-hash/pypy/translator/c/test/test_newgc.py
Log:
Pfew. Work until test_hash_preservation works with the mark&sweep GC.
All other framework GCs are broken right now.
Modified: pypy/branch/gc-hash/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/gc-hash/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/branch/gc-hash/pypy/rpython/lltypesystem/lloperation.py Tue Oct 13 20:15:53 2009
@@ -440,7 +440,7 @@
'gc_pop_alive_pyobj': LLOp(),
'gc_reload_possibly_moved': LLOp(),
# see rlib/objectmodel for gc_identityhash and gc_id
- 'gc_identityhash': LLOp(canraise=(MemoryError,), sideeffects=False),
+ 'gc_identityhash': LLOp(sideeffects=False),
'gc_id': LLOp(canraise=(MemoryError,), sideeffects=False),
'gc_set_max_heap_size': LLOp(),
'gc_can_move' : LLOp(sideeffects=False),
Modified: pypy/branch/gc-hash/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/gc-hash/pypy/rpython/memory/gc/base.py (original)
+++ pypy/branch/gc-hash/pypy/rpython/memory/gc/base.py Tue Oct 13 20:15:53 2009
@@ -123,9 +123,6 @@
def malloc_nonmovable(self, typeid, length=0, zero=False):
return self.malloc(typeid, length, zero)
- def id(self, ptr):
- return lltype.cast_ptr_to_int(ptr)
-
def can_move(self, addr):
return False
Modified: pypy/branch/gc-hash/pypy/rpython/memory/gc/marksweep.py
==============================================================================
--- pypy/branch/gc-hash/pypy/rpython/memory/gc/marksweep.py (original)
+++ pypy/branch/gc-hash/pypy/rpython/memory/gc/marksweep.py Tue Oct 13 20:15:53 2009
@@ -19,6 +19,9 @@
('pool', X_POOL_PTR))
X_CLONE_PTR = lltype.Ptr(X_CLONE)
+FL_WITHHASH = 0x01
+FL_CURPOOL = 0x02
+
memoryError = MemoryError()
class MarkSweepGC(GCBase):
HDR = lltype.ForwardReference()
@@ -27,9 +30,10 @@
# systems allocator and can't walk the heap
HDR.become(lltype.Struct('header', ('typeid16', rffi.USHORT),
('mark', lltype.Bool),
- ('curpool_flag', lltype.Bool),
+ ('flags', lltype.Char),
('next', HDRPTR)))
typeid_is_in_field = 'typeid16'
+ withhash_flag_is_in_field = 'flags', FL_WITHHASH
POOL = lltype.GcStruct('gc_pool')
POOLPTR = lltype.Ptr(POOL)
@@ -102,7 +106,7 @@
hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
hdr.typeid16 = typeid16
hdr.mark = False
- hdr.curpool_flag = False
+ hdr.flags = '\x00'
if has_finalizer:
hdr.next = self.malloced_objects_with_finalizer
self.malloced_objects_with_finalizer = hdr
@@ -139,7 +143,7 @@
hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
hdr.typeid16 = typeid16
hdr.mark = False
- hdr.curpool_flag = False
+ hdr.flags = '\x00'
if has_finalizer:
hdr.next = self.malloced_objects_with_finalizer
self.malloced_objects_with_finalizer = hdr
@@ -178,7 +182,7 @@
hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
hdr.typeid16 = typeid16
hdr.mark = False
- hdr.curpool_flag = False
+ hdr.flags = '\x00'
hdr.next = self.malloced_objects
self.malloced_objects = hdr
self.bytes_malloced = bytes_malloced
@@ -213,7 +217,7 @@
hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
hdr.typeid16 = typeid16
hdr.mark = False
- hdr.curpool_flag = False
+ hdr.flags = '\x00'
hdr.next = self.malloced_objects
self.malloced_objects = hdr
self.bytes_malloced = bytes_malloced
@@ -516,7 +520,7 @@
hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
hdr.typeid16 = typeid
hdr.mark = False
- hdr.curpool_flag = False
+ hdr.flags = '\x00'
def init_gc_object_immortal(self, addr, typeid, flags=0):
# prebuilt gc structures always have the mark bit set
@@ -524,7 +528,7 @@
hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
hdr.typeid16 = typeid
hdr.mark = True
- hdr.curpool_flag = False
+ hdr.flags = '\x00'
# experimental support for thread cloning
def x_swap_pool(self, newpool):
@@ -596,7 +600,8 @@
hdr = hdr.next # skip the POOL object itself
while hdr:
next = hdr.next
- hdr.curpool_flag = True # mark all objects from malloced_list
+ # mark all objects from malloced_list
+ hdr.flags = chr(ord(hdr.flags) | FL_CURPOOL)
hdr.next = lltype.nullptr(self.HDR) # abused to point to the copy
oldobjects.append(llmemory.cast_ptr_to_adr(hdr))
hdr = next
@@ -613,7 +618,7 @@
continue # pointer is NULL
oldhdr = llmemory.cast_adr_to_ptr(oldobj_addr - size_gc_header,
self.HDRPTR)
- if not oldhdr.curpool_flag:
+ if not (ord(oldhdr.flags) & FL_CURPOOL):
continue # ignore objects that were not in the malloced_list
newhdr = oldhdr.next # abused to point to the copy
if not newhdr:
@@ -645,13 +650,13 @@
saved_id = newhdr.typeid16 # XXX hack needed for genc
saved_flg1 = newhdr.mark
- saved_flg2 = newhdr.curpool_flag
+ saved_flg2 = newhdr.flags
saved_next = newhdr.next # where size_gc_header == 0
raw_memcopy(oldobj_addr, newobj_addr, size)
- newhdr.typeid16 = saved_id
- newhdr.mark = saved_flg1
- newhdr.curpool_flag = saved_flg2
- newhdr.next = saved_next
+ newhdr.typeid16 = saved_id
+ newhdr.mark = saved_flg1
+ newhdr.flags = saved_flg2
+ newhdr.next = saved_next
offsets = self.offsets_to_gc_pointers(typeid)
i = 0
@@ -685,7 +690,7 @@
next = lltype.nullptr(self.HDR)
while oldobjects.non_empty():
hdr = llmemory.cast_adr_to_ptr(oldobjects.pop(), self.HDRPTR)
- hdr.curpool_flag = False # reset the flag
+ hdr.flags = chr(ord(hdr.flags) &~ FL_CURPOOL) # reset the flag
hdr.next = next
next = hdr
oldobjects.delete()
@@ -700,6 +705,17 @@
# reinstall the pool that was current at the beginning of x_clone()
clonedata.pool = self.x_swap_pool(curpool)
+ def identityhash(self, obj):
+ obj = llmemory.cast_ptr_to_adr(obj)
+ size_gc_header = self.gcheaderbuilder.size_gc_header
+ gc_info = obj - size_gc_header
+ hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
+ if ord(hdr.flags) & FL_WITHHASH:
+ obj += self.get_size(obj)
+ return obj.signed[0]
+ else:
+ return llmemory.cast_adr_to_int(obj)
+
class PrintingMarkSweepGC(MarkSweepGC):
_alloc_flavor_ = "raw"
Modified: pypy/branch/gc-hash/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/gc-hash/pypy/rpython/memory/gctransform/framework.py (original)
+++ pypy/branch/gc-hash/pypy/rpython/memory/gctransform/framework.py Tue Oct 13 20:15:53 2009
@@ -337,6 +337,10 @@
[annmodel.SomeBool()],
s_gcref)
+ self.identityhash_ptr = getfn(GCClass.identityhash.im_func,
+ [s_gc, s_gcref],
+ annmodel.SomeInteger())
+
if GCClass.moving_gc:
self.id_ptr = getfn(GCClass.id.im_func,
[s_gc, s_gcref], annmodel.SomeInteger(),
@@ -435,7 +439,20 @@
def gc_field_values_for(self, obj):
hdr = self.gcdata.gc.gcheaderbuilder.header_of_object(obj)
HDR = self._gc_HDR
- return [getattr(hdr, fldname) for fldname in HDR._names]
+ withhash, flag = self.gcdata.gc.withhash_flag_is_in_field
+ result = []
+ for fldname in HDR._names:
+ x = getattr(hdr, fldname)
+ if fldname == withhash:
+ TYPE = lltype.typeOf(x)
+ x = lltype.cast_primitive(lltype.Signed, x)
+ if hasattr(obj._normalizedcontainer(), '_hash_cache_'):
+ x |= flag
+ else:
+ x &= ~flag
+ x = lltype.cast_primitive(TYPE, x)
+ result.append(x)
+ return result
def finish_tables(self):
group = self.layoutbuilder.close_table()
@@ -713,6 +730,14 @@
resulttype=llmemory.Address)
hop.cast_result(v_addr)
+ def gct_gc_identityhash(self, hop):
+ [v_ptr] = hop.spaceop.args
+ v_adr = hop.genop("cast_ptr_to_adr", [v_ptr],
+ resulttype=llmemory.Address)
+ hop.genop("direct_call",
+ [self.identityhash_ptr, self.c_const_gc, v_adr],
+ resultvar=hop.spaceop.result)
+
def gct_gc_id(self, hop):
if self.id_ptr is not None:
livevars = self.push_roots(hop)
Modified: pypy/branch/gc-hash/pypy/translator/c/database.py
==============================================================================
--- pypy/branch/gc-hash/pypy/translator/c/database.py (original)
+++ pypy/branch/gc-hash/pypy/translator/c/database.py Tue Oct 13 20:15:53 2009
@@ -65,12 +65,17 @@
self.instrument_ncounter = 0
- def gettypedefnode(self, T, varlength=1):
+ def gettypedefnode(self, T, varlength=1, needs_hash=False):
if varlength <= 1:
varlength = 1 # it's C after all
key = T
else:
key = T, varlength
+ if needs_hash:
+ if self.gcpolicy.stores_hash_at_the_end:
+ key = key, 'hash'
+ else:
+ needs_hash = False
try:
node = self.structdefnodes[key]
except KeyError:
@@ -78,7 +83,7 @@
if isinstance(T, FixedSizeArray):
node = FixedSizeArrayDefNode(self, T)
else:
- node = StructDefNode(self, T, varlength)
+ node = StructDefNode(self, T, varlength, needs_hash)
elif isinstance(T, Array):
if barebonearray(T):
node = BareBoneArrayDefNode(self, T, varlength)
@@ -95,7 +100,8 @@
self.pendingsetupnodes.append(node)
return node
- def gettype(self, T, varlength=1, who_asks=None, argnames=[]):
+ def gettype(self, T, varlength=1, who_asks=None, argnames=[],
+ needs_hash=False):
if isinstance(T, Primitive) or T == GCREF:
return PrimitiveType[T]
elif isinstance(T, Ptr):
@@ -109,7 +115,8 @@
typename = self.gettype(T.TO) # who_asks not propagated
return typename.replace('@', '*@')
elif isinstance(T, (Struct, Array, _WeakRefType)):
- node = self.gettypedefnode(T, varlength=varlength)
+ node = self.gettypedefnode(T, varlength=varlength,
+ needs_hash=needs_hash)
if who_asks is not None:
who_asks.dependencies[node] = True
return node.gettype()
Modified: pypy/branch/gc-hash/pypy/translator/c/gc.py
==============================================================================
--- pypy/branch/gc-hash/pypy/translator/c/gc.py (original)
+++ pypy/branch/gc-hash/pypy/translator/c/gc.py Tue Oct 13 20:15:53 2009
@@ -12,6 +12,7 @@
class BasicGcPolicy(object):
requires_stackless = False
+ stores_hash_at_the_end = False
def __init__(self, db, thread_enabled=False):
self.db = db
@@ -42,9 +43,6 @@
def array_gcheader_initdata(self, defnode):
return self.common_gcheader_initdata(defnode)
- def struct_after_definition(self, defnode):
- return []
-
def compilation_info(self):
if not self.db:
return ExternalCompilationInfo()
@@ -290,6 +288,7 @@
class FrameworkGcPolicy(BasicGcPolicy):
transformerclass = framework.FrameworkGCTransformer
+ stores_hash_at_the_end = True
def struct_setup(self, structdefnode, rtti):
if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'):
Modified: pypy/branch/gc-hash/pypy/translator/c/node.py
==============================================================================
--- pypy/branch/gc-hash/pypy/translator/c/node.py (original)
+++ pypy/branch/gc-hash/pypy/translator/c/node.py Tue Oct 13 20:15:53 2009
@@ -37,11 +37,12 @@
class StructDefNode:
typetag = 'struct'
- def __init__(self, db, STRUCT, varlength=1):
+ def __init__(self, db, STRUCT, varlength=1, hash_at_end=False):
self.db = db
self.STRUCT = STRUCT
self.LLTYPE = STRUCT
self.varlength = varlength
+ self.hash_at_end = hash_at_end
if varlength == 1:
basename = STRUCT._name
with_number = True
@@ -49,6 +50,8 @@
basename = db.gettypedefnode(STRUCT).barename
basename = '%s_len%d' % (basename, varlength)
with_number = False
+ if hash_at_end:
+ basename += '_hash'
if STRUCT._hints.get('union'):
self.typetag = 'union'
assert STRUCT._gckind == 'raw' # not supported: "GcUnion"
@@ -94,6 +97,8 @@
else:
typename = db.gettype(T, who_asks=self)
self.fields.append((self.c_struct_field_name(name), typename))
+ if self.hash_at_end:
+ self.fields.append(('_hash', 'long @'))
self.gcinfo # force it to be computed
def computegcinfo(self):
@@ -149,8 +154,6 @@
if is_empty:
yield '\t' + 'char _dummy; /* this struct is empty */'
yield '};'
- for line in self.db.gcpolicy.struct_after_definition(self):
- yield line
def visitor_lines(self, prefix, on_field):
for name in self.fieldnames:
@@ -448,7 +451,8 @@
self.obj = obj
#self.dependencies = {}
self.typename = db.gettype(T) #, who_asks=self)
- self.implementationtypename = db.gettype(T, varlength=self.getlength())
+ self.implementationtypename = db.gettype(T, varlength=self.getlength(),
+ needs_hash=hasattr(obj, '_hash_cache_'))
parent, parentindex = parentlink(obj)
if parent is None:
self.name = db.namespace.uniquename('g_' + self.basename())
@@ -519,7 +523,8 @@
data = []
if needs_gcheader(self.T):
- for i, thing in enumerate(self.db.gcpolicy.struct_gcheader_initdata(self)):
+ hdr = self.db.gcpolicy.struct_gcheader_initdata(self)
+ for i, thing in enumerate(hdr):
data.append(('gcheader%d'%i, thing))
for name in defnode.fieldnames:
@@ -533,6 +538,9 @@
if hasattr(self.T, "_hints") and self.T._hints.get('union'):
data = data[0:1]
+ if hasattr(self.obj, '_hash_cache_'):
+ data.append(('_hash', self.obj._hash_cache_))
+
for name, value in data:
c_expr = defnode.access_expr(self.name, name)
lines = generic_initializationexpr(self.db, value, c_expr,
Modified: pypy/branch/gc-hash/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/gc-hash/pypy/translator/c/test/test_newgc.py (original)
+++ pypy/branch/gc-hash/pypy/translator/c/test/test_newgc.py Tue Oct 13 20:15:53 2009
@@ -689,6 +689,31 @@
def test_resizable_buffer(self):
assert self.run('resizable_buffer')
+ def define_hash_preservation(cls):
+ from pypy.rlib.objectmodel import compute_hash
+ from pypy.rlib.objectmodel import current_object_addr_as_int
+ class C:
+ pass
+ class D(C):
+ pass
+ c = C()
+ d = D()
+ h_d = compute_hash(d) # force to be cached on 'd', but not on 'c'
+ h_t = compute_hash(("Hi", None, (7.5, 2, d)))
+ #
+ def f():
+ d2 = D()
+ if compute_hash(d2) != current_object_addr_as_int(d2): return 11
+ if compute_hash(c) != compute_hash(c): return 12
+ if compute_hash(d) != h_d: return 13
+ if compute_hash(("Hi", None, (7.5, 2, d))) != h_t: return 14
+ return 42
+ return f
+
+ def test_hash_preservation(self):
+ res = self.run('hash_preservation')
+ assert res == 42
+
class TestSemiSpaceGC(TestUsingFramework, snippet.SemiSpaceGCTestDefines):
gcpolicy = "semispace"
should_be_moving = True
More information about the Pypy-commit
mailing list