Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r74943:e6ad4389d70b
Date: 2014-12-15 17:19 +0000
http://bitbucket.org/pypy/pypy/changeset/e6ad4389d70b/

Log:    Do a ll_clear_indexes() instead of allocating a new array for
        d.indexes when we can

diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -330,6 +330,20 @@
     keepalive_until_here(newp)
     return newp
 
[email protected]_look_inside
[email protected]()
+def ll_arrayclear(p):
+    # Equivalent to memset(array, 0).  Only for GcArray(primitive-type) for 
now.
+    from rpython.rlib.objectmodel import keepalive_until_here
+
+    length = len(p)
+    ARRAY = lltype.typeOf(p).TO
+    offset = llmemory.itemoffsetof(ARRAY, 0)
+    dest_addr = llmemory.cast_ptr_to_adr(p) + offset
+    llmemory.raw_memclear(dest_addr, llmemory.sizeof(ARRAY.OF) * length)
+    keepalive_until_here(p)
+
+
 def no_release_gil(func):
     func._dont_inline_ = True
     func._no_release_gil_ = True
diff --git a/rpython/rlib/test/test_rgc.py b/rpython/rlib/test/test_rgc.py
--- a/rpython/rlib/test/test_rgc.py
+++ b/rpython/rlib/test/test_rgc.py
@@ -158,6 +158,16 @@
     assert a2[2].x == 3
     assert a2[2].y == 15
 
+def test_ll_arrayclear():
+    TYPE = lltype.GcArray(lltype.Signed)
+    a1 = lltype.malloc(TYPE, 10)
+    for i in range(10):
+        a1[i] = 100 + i
+    rgc.ll_arrayclear(a1)
+    assert len(a1) == 10
+    for i in range(10):
+        assert a1[i] == 0
+
 def test__contains_gcptr():
     assert not rgc._contains_gcptr(lltype.Signed)
     assert not rgc._contains_gcptr(
diff --git a/rpython/rtyper/lltypesystem/rordereddict.py 
b/rpython/rtyper/lltypesystem/rordereddict.py
--- a/rpython/rtyper/lltypesystem/rordereddict.py
+++ b/rpython/rtyper/lltypesystem/rordereddict.py
@@ -418,6 +418,7 @@
 TYPE_LONG  = lltype.Unsigned
 
 def ll_malloc_indexes_and_choose_lookup(d, n):
+    # keep in sync with ll_clear_indexes() below
     if n <= 256:
         d.indexes = lltype.cast_opaque_ptr(llmemory.GCREF,
                                            lltype.malloc(DICTINDEX_BYTE.TO, n,
@@ -439,6 +440,16 @@
                                                          zero=True))
         d.lookup_function_no = FUNC_LONG
 
+def ll_clear_indexes(d, n):
+    if n <= 256:
+        rgc.ll_arrayclear(lltype.cast_opaque_ptr(DICTINDEX_BYTE, d.indexes))
+    elif n <= 65536:
+        rgc.ll_arrayclear(lltype.cast_opaque_ptr(DICTINDEX_SHORT, d.indexes))
+    elif IS_64BIT and n <= 2 ** 32:
+        rgc.ll_arrayclear(lltype.cast_opaque_ptr(DICTINDEX_INT, d.indexes))
+    else:
+        rgc.ll_arrayclear(lltype.cast_opaque_ptr(DICTINDEX_LONG, d.indexes))
+
 def ll_call_insert_clean_function(d, hash, i):
     DICT = lltype.typeOf(d).TO
     if d.lookup_function_no == FUNC_BYTE:
@@ -704,13 +715,17 @@
         ll_dict_reindex(d, new_size)
 
 def ll_dict_reindex(d, new_size):
-    ll_malloc_indexes_and_choose_lookup(d, new_size)
+    if bool(d.indexes) and _ll_len_of_d_indexes(d) == new_size:
+        ll_clear_indexes(d, new_size)   # hack: we can reuse the same array
+    else:
+        ll_malloc_indexes_and_choose_lookup(d, new_size)
     d.resize_counter = new_size * 2 - d.num_items * 3
     assert d.resize_counter > 0
     #
     entries = d.entries
     i = 0
-    while i < d.num_used_items:
+    ibound = d.num_used_items
+    while i < ibound:
         if entries.valid(i):
             hash = entries.hash(i)
             ll_call_insert_clean_function(d, hash, i)
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to