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

Reply via email to