[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