[pypy-commit] pypy use-mmap: arena_mmap() returns page-aligned memory, so we can get rid of this

arigo pypy.commits at gmail.com
Mon Jul 11 18:03:58 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: use-mmap
Changeset: r85664:96909c906c52
Date: 2016-07-12 00:05 +0200
http://bitbucket.org/pypy/pypy/changeset/96909c906c52/

Log:	arena_mmap() returns page-aligned memory, so we can get rid of this
	page-realignment indirection

diff --git a/rpython/memory/gc/minimarkpage.py b/rpython/memory/gc/minimarkpage.py
--- a/rpython/memory/gc/minimarkpage.py
+++ b/rpython/memory/gc/minimarkpage.py
@@ -18,11 +18,10 @@
 
 ARENA_PTR = lltype.Ptr(lltype.ForwardReference())
 ARENA = lltype.Struct('ArenaReference',
-    # -- The address of the arena, as returned by malloc()
+    # -- The address of the arena, as returned by arena_mmap()
     ('base', llmemory.Address),
-    # -- The number of free and the total number of pages in the arena
+    # -- The number of free pages in the arena
     ('nfreepages', lltype.Signed),
-    ('totalpages', lltype.Signed),
     # -- A chained list of free pages in the arena.  Ends with NULL.
     ('freepages', llmemory.Address),
     # -- A linked list of arenas.  See below.
@@ -113,14 +112,14 @@
         for i in range(1, length):
             self.nblocks_for_size[i] = (page_size - self.hdrsize) // (WORD * i)
         #
-        self.max_pages_per_arena = arena_size // page_size
+        self.pages_per_arena = arena_size // page_size
         self.arenas_lists = lltype.malloc(rffi.CArray(ARENA_PTR),
-                                          self.max_pages_per_arena,
+                                          self.pages_per_arena,
                                           flavor='raw', zero=True,
                                           immortal=True)
         # this is used in mass_free() only
         self.old_arenas_lists = lltype.malloc(rffi.CArray(ARENA_PTR),
-                                              self.max_pages_per_arena,
+                                              self.pages_per_arena,
                                               flavor='raw', zero=True,
                                               immortal=True)
         #
@@ -158,7 +157,7 @@
         self.current_arena = ARENA_NULL
         #
         # guarantee that 'arenas_lists[1:min_empty_nfreepages]' are all empty
-        self.min_empty_nfreepages = self.max_pages_per_arena
+        self.min_empty_nfreepages = self.pages_per_arena
         #
         # part of current_arena might still contain uninitialized pages
         self.num_uninitialized_pages = 0
@@ -284,7 +283,7 @@
         # but > 0.  Use caching with 'min_empty_nfreepages', which guarantees
         # that 'arenas_lists[1:min_empty_nfreepages]' are all empty.
         i = self.min_empty_nfreepages
-        while i < self.max_pages_per_arena:
+        while i < self.pages_per_arena:
             #
             if self.arenas_lists[i] != ARENA_NULL:
                 #
@@ -328,30 +327,21 @@
             self.mreset_arenas = arena.nextarena
         else:
             #
-            # 'arena_base' points to the start of malloced memory.  It might
-            # not be a page-aligned address depending on the underlying call
-            # (although with mmap() it should be).
+            # 'arena_base' points to the start of malloced memory.  It is
+            # aligned to a physical page (although self.page_size is
+            # typically two physical pages on 64-bit).
             arena_base = llarena.arena_mmap(self.arena_size)
             if not arena_base:
                 out_of_memory("out of memory: couldn't allocate the next arena")
-            arena_end = arena_base + self.arena_size
-            #
-            # 'firstpage' points to the first unused page
-            firstpage = start_of_page(arena_base + self.page_size - 1,
-                                      self.page_size)
-            # 'npages' is the number of full pages just allocated
-            npages = (arena_end - firstpage) // self.page_size
             #
             # Allocate an ARENA object and initialize it
             arena = lltype.malloc(ARENA, flavor='raw', track_allocation=False)
             arena.base = arena_base
-            arena.totalpages = npages
         #
         arena.nfreepages = 0        # they are all uninitialized pages
-        arena.freepages = start_of_page(arena.base + self.page_size - 1,
-                                        self.page_size)
+        arena.freepages = arena.base
         arena.nextarena = ARENA_NULL
-        self.num_uninitialized_pages = arena.totalpages
+        self.num_uninitialized_pages = self.pages_per_arena
         self.current_arena = arena
         #
     allocate_new_arena._dont_inline_ = True
@@ -443,17 +433,17 @@
             self.arenas_lists, self.old_arenas_lists)
         #
         i = 0
-        while i < self.max_pages_per_arena:
+        while i < self.pages_per_arena:
             self.arenas_lists[i] = ARENA_NULL
             i += 1
         #
         i = 0
-        while i < self.max_pages_per_arena:
+        while i < self.pages_per_arena:
             arena = self.old_arenas_lists[i]
             while arena != ARENA_NULL:
                 nextarena = arena.nextarena
                 #
-                if arena.nfreepages == arena.totalpages:
+                if arena.nfreepages == self.pages_per_arena:
                     #
                     # The whole arena is empty.  Move it to the dying list.
                     arena.nextarena = self.dying_arenas
@@ -465,8 +455,8 @@
                 else:
                     # Insert 'arena' in the correct arenas_lists[n]
                     n = arena.nfreepages
-                    ll_assert(n < self.max_pages_per_arena,
-                             "totalpages != nfreepages >= max_pages_per_arena")
+                    ll_assert(n < self.pages_per_arena,
+                             "nfreepages > pages_per_arena")
                     arena.nextarena = self.arenas_lists[n]
                     self.arenas_lists[n] = arena
                 #
@@ -543,7 +533,7 @@
         """Free a whole page."""
         #
         # Insert the freed page in the arena's 'freepages' list.
-        # If nfreepages == totalpages, then it will be freed at the
+        # If nfreepages == pages_per_arena, then it will be freed at the
         # end of mass_free().
         arena = page.arena
         arena.nfreepages += 1
@@ -636,21 +626,6 @@
 # ____________________________________________________________
 # Helpers to go from a pointer to the start of its page
 
-def start_of_page(addr, page_size):
-    """Return the address of the start of the page that contains 'addr'."""
-    if we_are_translated():
-        offset = llmemory.cast_adr_to_int(addr) % page_size
-        return addr - offset
-    else:
-        return _start_of_page_untranslated(addr, page_size)
-
-def _start_of_page_untranslated(addr, page_size):
-    assert isinstance(addr, llarena.fakearenaaddress)
-    shift = WORD  # for testing, we assume that the whole arena is not
-                  # on a page boundary
-    ofs = ((addr.offset - shift) // page_size) * page_size + shift
-    return llarena.fakearenaaddress(addr.arena, ofs)
-
 def _dummy_size(size):
     if we_are_translated():
         return size
diff --git a/rpython/memory/gc/test/test_minimarkpage.py b/rpython/memory/gc/test/test_minimarkpage.py
--- a/rpython/memory/gc/test/test_minimarkpage.py
+++ b/rpython/memory/gc/test/test_minimarkpage.py
@@ -7,19 +7,18 @@
 from rpython.rtyper.lltypesystem.llmemory import cast_ptr_to_adr
 
 NULL = llmemory.NULL
-SHIFT = WORD
 hdrsize = llmemory.raw_malloc_usage(llmemory.sizeof(PAGE_HEADER))
 
 
 def test_allocate_arena():
-    ac = ArenaCollection(SHIFT + 64*20, 64, 1)
+    ac = ArenaCollection(64*20, 64, 1)
     ac.allocate_new_arena()
     assert ac.num_uninitialized_pages == 20
     upages = ac.current_arena.freepages
     upages + 64*20   # does not raise
     py.test.raises(llarena.ArenaError, "upages + 64*20 + 1")
     #
-    ac = ArenaCollection(SHIFT + 64*20 + 7, 64, 1)
+    ac = ArenaCollection(64*20 + 7, 64, 1)
     ac.allocate_new_arena()
     assert ac.num_uninitialized_pages == 20
     upages = ac.current_arena.freepages


More information about the pypy-commit mailing list