Author: Armin Rigo <[email protected]>
Branch: stmgc-c8-dictstrategy
Changeset: r80954:d06bd49db189
Date: 2015-11-25 17:08 +0100
http://bitbucket.org/pypy/pypy/changeset/d06bd49db189/
Log: in-progress, still crashing
diff --git a/rpython/rlib/rstm.py b/rpython/rlib/rstm.py
--- a/rpython/rlib/rstm.py
+++ b/rpython/rlib/rstm.py
@@ -293,7 +293,10 @@
hiter.prev = entrypp
return entrypp[0]
-_HASHTABLE_OBJ = lltype.GcStruct('HASHTABLE_OBJ',
+class GcStmHashtable(lltype.GcStruct):
+ pass
+
+_HASHTABLE_OBJ = GcStmHashtable('HASHTABLE_OBJ',
('ll_raw_hashtable', _STM_HASHTABLE_P),
hints={'immutable': True},
rtti=True,
@@ -357,11 +360,12 @@
NULL_GCREF = lltype.nullptr(llmemory.GCREF.TO)
class HashtableForTest(object):
+ _TYPE = lltype.Ptr(_HASHTABLE_OBJ)
def __init__(self):
self._content = {} # dict {integer: Entry(obj=GCREF)}
def _cleanup_(self):
- raise Exception("cannot translate a prebuilt rstm.Hashtable object")
+ raise Exception("this class should be special-cased")
def get(self, key):
assert type(key) is int
@@ -386,15 +390,18 @@
except KeyError:
pass
+ def _live_items(self):
+ return [self.lookup(key) for key, v in self._content.items()
+ if v.object != NULL_GCREF]
+
def len(self):
- items = [self.lookup(key) for key, v in self._content.items() if
v.object != NULL_GCREF]
- return len(items)
+ return len(self._live_items())
def len_estimate(self):
return len(self._content)
def list(self):
- items = [self.lookup(key) for key, v in self._content.items() if
v.object != NULL_GCREF]
+ items = self._live_items()
count = len(items)
for i in range(3):
items.append("additional garbage for testing")
@@ -418,6 +425,9 @@
self.index = r_uint(key)
self._obj = NULL_GCREF
+ def _cleanup_(self):
+ raise Exception("cannot translate EntryObjectForTest")
+
def _getobj(self):
return self._obj
def _setobj(self, nvalue):
@@ -431,12 +441,22 @@
self.hashtable = hashtable
self.iterator = iterator
+ def _cleanup_(self):
+ raise Exception("cannot translate IterEntriesForTest")
+
def next(self):
while 1:
entry = next(self.iterator)
if entry._obj:
return entry
+class _Entry(ExtRegistryEntry):
+ _type_ = HashtableForTest
+
+ def compute_annotation(self):
+ from rpython.translator.stm import hashtable
+ return hashtable.compute_annotation(self.bookkeeper, self.instance)
+
# ____________________________________________________________
_STM_QUEUE_P = rffi.COpaquePtr('stm_queue_t')
diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py
--- a/rpython/translator/c/genc.py
+++ b/rpython/translator/c/genc.py
@@ -865,6 +865,7 @@
def gen_stm_prebuilt(f, database):
from rpython.translator.c.primitive import name_signed
+ from rpython.translator.stm.hashtable import gen_prebuilt_hashtables
#
print >> f, '#include "common_header.h"'
print >> f, '#include "structdef.h"'
@@ -894,6 +895,7 @@
print >> f, '\t%d,' % (i,)
print >> f, '\t-1'
print >> f, '};'
+ gen_prebuilt_hashtables(f, database)
print >> f
print >> f, '#include "preimpl.h"'
print >> f, '#include "src/rtyper.h"'
diff --git a/rpython/translator/stm/hashtable.py
b/rpython/translator/stm/hashtable.py
new file mode 100644
--- /dev/null
+++ b/rpython/translator/stm/hashtable.py
@@ -0,0 +1,76 @@
+from rpython.rlib import rstm
+from rpython.rtyper.lltypesystem import lltype
+from rpython.rtyper.llannotation import lltype_to_annotation
+from rpython.translator.c.node import ContainerNodeFactory, StructNode
+
+
+def compute_annotation(bookkeeper, hashtable):
+ if not hasattr(hashtable, '_obj'):
+ h = lltype.malloc(rstm._HASHTABLE_OBJ, zero=True)
+ hashtable._obj = h._obj
+ translator = bookkeeper.annotator.translator
+ try:
+ prebuilt_hashtables = translator._prebuilt_hashtables
+ except AttributeError:
+ prebuilt_hashtables = translator._prebuilt_hashtables = {}
+ prebuilt_hashtables[h._obj] = hashtable
+ #
+ for entry in hashtable._content.values():
+ if entry._obj:
+ bookkeeper.immutablevalue(entry._obj)
+ bookkeeper.immutablevalue(lltype.nullptr(rstm._STM_HASHTABLE_ENTRY))
+ #
+ return lltype_to_annotation(lltype.Ptr(rstm._HASHTABLE_OBJ))
+
+
+def gen_prebuilt_hashtables(f, database):
+ nodes = [node for node in database.globalcontainers()
+ if isinstance(node, StmHashtableNode)]
+ print >> f
+ print >> f, '#define STM_PREBUILT_HASHTABLES %d' % len(nodes)
+ if len(nodes) == 0:
+ return
+ type_id = database.gctransformer.get_type_id(rstm._STM_HASHTABLE_ENTRY)
+ expr_type_id = database.get(type_id)
+ print >> f, '#define STM_HASHTABLE_ENTRY_TYPEID %s' % (expr_type_id,)
+ print >> f
+ print >> f, 'struct _hashtable_descr_s {'
+ print >> f, '\tUnsigned key;'
+ print >> f, '\trpygcchar_t *value;'
+ print >> f, '};'
+ print >> f, 'static struct _hashtable_descr_s hashtable_descs[] = {'
+ for node in nodes:
+ assert node.globalgcnum >= 0
+ items = node.get_hashtable_content()
+ items.sort(key=lambda entry: entry.index)
+ print >> f, '\t{ %d, (rpygcchar_t *)%d },' % (node.globalgcnum,
+ len(items))
+ for entry in items:
+ expr = database.get(entry.object, static=True)
+ print >> f, '\t{ %d, %s },' % (entry.index, expr)
+ print >> f
+ print >> f, '};'
+
+
+class StmHashtableNode(StructNode):
+ nodekind = 'stmhashtable'
+
+ def __init__(self, db, T, obj):
+ StructNode.__init__(self, db, T, obj)
+ # hack to force this type to exist
+ T = rstm._STM_HASHTABLE_ENTRY
+ container = lltype.malloc(T, zero=True)._as_obj()
+ db.gctransformer.consider_constant(T, container)
+
+ def get_hashtable_content(self):
+ h = self.db.translator._prebuilt_hashtables[self.obj]
+ return h._live_items()
+
+ def basename(self):
+ return 'stmhashtable'
+
+ def enum_dependencies(self):
+ for entry in self.get_hashtable_content():
+ yield entry.object
+
+ContainerNodeFactory[rstm.GcStmHashtable] = StmHashtableNode
diff --git a/rpython/translator/stm/src_stm/extracode.h
b/rpython/translator/stm/src_stm/extracode.h
--- a/rpython/translator/stm/src_stm/extracode.h
+++ b/rpython/translator/stm/src_stm/extracode.h
@@ -37,6 +37,34 @@
stmcb_light_finalizer = &_stm_call_finalizer;
}
+void pypy_stm_setup_prebuilt_hashtables(void)
+{
+#if STM_PREBUILT_HASHTABLES > 0
+ struct _hashtable_descr_s *hdesc = hashtable_descs;
+ int i;
+ long count;
+ pypy_HASHTABLE_OBJ0_t *htobj;
+ stm_hashtable_t *ht;
+
+ stm_hashtable_entry_userdata = STM_HASHTABLE_ENTRY_TYPEID;
+ for (i = 0; i < STM_PREBUILT_HASHTABLES; i++) {
+ /* Every hashtable is one header hdesc entry followed by N hdescs.
+ The header abuses 'key' as an index inside rpy_prebuilt and
+ 'value' as the number of entries that follow. */
+ htobj = (pypy_HASHTABLE_OBJ0_t *)rpy_prebuilt[hdesc->key];
+ htobj->ha_ll_raw_hashtable = ht = stm_hashtable_create();
+ count = (long)hdesc->value;
+ hdesc++;
+ while (count > 0) {
+ stm_hashtable_write((object_t *)htobj, ht, hdesc->key,
+ (object_t *)hdesc->value, &stm_thread_local);
+ hdesc++;
+ count--;
+ }
+ }
+#endif
+}
+
void pypy_stm_register_thread_local(void)
{
stm_register_thread_local(&stm_thread_local);
diff --git a/rpython/translator/stm/src_stm/stmgcintf.c
b/rpython/translator/stm/src_stm/stmgcintf.c
--- a/rpython/translator/stm/src_stm/stmgcintf.c
+++ b/rpython/translator/stm/src_stm/stmgcintf.c
@@ -62,6 +62,8 @@
stm_enter_transactional_zone(&stm_thread_local);
stm_become_inevitable(&stm_thread_local, "start-up");
stm_rewind_jmp_leaveframe(&stm_thread_local, &rjbuf);
+
+ pypy_stm_setup_prebuilt_hashtables();
}
void pypy_stm_set_transaction_length(double fraction)
diff --git a/rpython/translator/stm/src_stm/stmgcintf.h
b/rpython/translator/stm/src_stm/stmgcintf.h
--- a/rpython/translator/stm/src_stm/stmgcintf.h
+++ b/rpython/translator/stm/src_stm/stmgcintf.h
@@ -10,6 +10,7 @@
void pypy_stm_setup(void);
void pypy_stm_teardown(void);
void pypy_stm_setup_prebuilt(void); /* generated into stm_prebuilt.c */
+void pypy_stm_setup_prebuilt_hashtables(void); /* " " " */
void pypy_stm_register_thread_local(void); /* generated into stm_prebuilt.c */
void pypy_stm_unregister_thread_local(void); /* generated into stm_prebuilt.c
*/
diff --git a/rpython/translator/stm/test/test_ztranslated.py
b/rpython/translator/stm/test/test_ztranslated.py
--- a/rpython/translator/stm/test/test_ztranslated.py
+++ b/rpython/translator/stm/test/test_ztranslated.py
@@ -799,3 +799,34 @@
t, cbuilder = self.compile(main)
data = cbuilder.cmdexec('')
assert 'ok!\n' in data
+
+ def test_hashtable_prebuilt(self):
+ FOO = lltype.GcStruct('FOO')
+ h = rstm.create_hashtable()
+ foo = lltype.malloc(FOO)
+ h.set(123, lltype.cast_opaque_ptr(llmemory.GCREF, foo))
+ h.set(345, lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(FOO)))
+
+ def main(argv):
+ assert h.list()[1] == 2
+ assert h.get(123) == lltype.cast_opaque_ptr(llmemory.GCREF, foo)
+ assert h.get(234) == lltype.nullptr(llmemory.GCREF.TO)
+ assert h.get(345) != lltype.nullptr(llmemory.GCREF.TO)
+ hiter = h.iterentries()
+ entry1 = hiter.next()
+ entry2 = hiter.next()
+ try:
+ hiter.next()
+ except StopIteration:
+ pass
+ else:
+ print "hiter.next() should return only twice here"
+ assert 0
+ assert ((entry1.index == 123 and entry2.index == 345) or
+ (entry1.index == 345 and entry2.index == 123))
+ print "ok!"
+ return 0
+
+ t, cbuilder = self.compile(main)
+ data = cbuilder.cmdexec('')
+ assert 'ok!\n' in data
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit