Bug 1396723 - Use DoublyLinkedList in mozjemalloc. r=froydnj

Mozjemalloc uses its own doubly linked list, which, being inherited from
C code, doesn't do much type checking, and, in practice, is rather
similar to DoublyLinkedList, so use the latter instead.

--HG--
extra : rebase_source : 9eb7334b6dde05f9af0eaea4184e532c69d0264e
This commit is contained in:
Mike Hommey 2017-09-02 08:55:42 +09:00
parent 0d8ed2b1a5
commit be1493b6fc
3 changed files with 42 additions and 89 deletions

View file

@ -1,75 +0,0 @@
/* -*- Mode: C; tab-width: 8; c-basic-offset: 8; indent-tabs-mode: t -*- */
/* vim:set softtabstop=8 shiftwidth=8 noet: */
/*-
* Copyright (C) the Mozilla Foundation.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice(s), this list of conditions and the following disclaimer as
* the first lines of this file unmodified other than the possible
* addition of one or more copyright notices.
* 2. Redistributions in binary form must reproduce the above copyright
* notice(s), this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#ifndef linkedlist_h__
#define linkedlist_h__
#include <stddef.h>
struct LinkedList {
LinkedList *next;
LinkedList *prev;
};
/* Convert from LinkedList* to foo*. */
#define LinkedList_Get(e, type, prop) \
(type*)((char*)(e) - offsetof(type, prop))
/* Insert |e| at the beginning of |l|. */
void LinkedList_InsertHead(LinkedList *l, LinkedList *e)
{
e->next = l;
e->prev = l->prev;
e->next->prev = e;
e->prev->next = e;
}
void LinkedList_Remove(LinkedList *e)
{
e->prev->next = e->next;
e->next->prev = e->prev;
e->next = e;
e->prev = e;
}
bool LinkedList_IsEmpty(LinkedList *e)
{
return e->next == e;
}
void LinkedList_Init(LinkedList *e)
{
e->next = e;
e->prev = e;
}
#endif

View file

@ -112,6 +112,7 @@
#include "mozilla/Sprintf.h"
#include "mozilla/Likely.h"
#include "mozilla/MacroArgs.h"
#include "mozilla/DoublyLinkedList.h"
#ifdef ANDROID
#define NO_TLS
@ -252,7 +253,6 @@ typedef long ssize_t;
#endif
#include "mozjemalloc_types.h"
#include "linkedlist.h"
/* Some tools, such as /dev/dsp wrappers, LD_PRELOAD libraries that
* happen to override mmap() and call dlsym() from their overridden
@ -627,7 +627,7 @@ struct arena_chunk_t {
*
* We're currently lazy and don't remove a chunk from this list when
* all its madvised pages are recommitted. */
LinkedList chunks_madvised_elem;
mozilla::DoublyLinkedListElement<arena_chunk_t> chunks_madvised_elem;
#endif
/* Number of dirty pages. */
@ -638,6 +638,21 @@ struct arena_chunk_t {
};
typedef rb_tree(arena_chunk_t) arena_chunk_tree_t;
#ifdef MALLOC_DOUBLE_PURGE
namespace mozilla {
template<>
struct GetDoublyLinkedListElement<arena_chunk_t>
{
static DoublyLinkedListElement<arena_chunk_t>& Get(arena_chunk_t* aThis)
{
return aThis->chunks_madvised_elem;
}
};
}
#endif
struct arena_run_t {
#if defined(MOZ_DEBUG) || defined(MOZ_DIAGNOSTIC_ASSERT_ENABLED)
uint32_t magic;
@ -709,7 +724,7 @@ struct arena_t {
#ifdef MALLOC_DOUBLE_PURGE
/* Head of a linked list of MADV_FREE'd-page-containing chunks this
* arena manages. */
LinkedList chunks_madvised;
mozilla::DoublyLinkedList<arena_chunk_t> chunks_madvised;
#endif
/*
@ -2699,7 +2714,7 @@ arena_chunk_init(arena_t *arena, arena_chunk_t *chunk, bool zeroed)
&chunk->map[arena_chunk_header_npages]);
#ifdef MALLOC_DOUBLE_PURGE
LinkedList_Init(&chunk->chunks_madvised_elem);
new (&chunk->chunks_madvised_elem) mozilla::DoublyLinkedListElement<arena_chunk_t>();
#endif
}
@ -2716,8 +2731,9 @@ arena_chunk_dealloc(arena_t *arena, arena_chunk_t *chunk)
}
#ifdef MALLOC_DOUBLE_PURGE
/* This is safe to do even if arena->spare is not in the list. */
LinkedList_Remove(&arena->spare->chunks_madvised_elem);
if (arena->chunks_madvised.ElementProbablyInList(arena->spare)) {
arena->chunks_madvised.remove(arena->spare);
}
#endif
chunk_dealloc((void *)arena->spare, chunksize, ARENA_CHUNK);
@ -2878,8 +2894,10 @@ arena_purge(arena_t *arena, bool all)
if (madvised) {
/* The chunk might already be in the list, but this
* makes sure it's at the front. */
LinkedList_Remove(&chunk->chunks_madvised_elem);
LinkedList_InsertHead(&arena->chunks_madvised, &chunk->chunks_madvised_elem);
if (arena->chunks_madvised.ElementProbablyInList(chunk)) {
arena->chunks_madvised.remove(chunk);
}
arena->chunks_madvised.pushFront(chunk);
}
#endif
}
@ -4023,7 +4041,7 @@ arena_new(arena_t *arena)
/* Initialize chunks. */
arena_chunk_tree_dirty_new(&arena->chunks_dirty);
#ifdef MALLOC_DOUBLE_PURGE
LinkedList_Init(&arena->chunks_madvised);
new (&arena->chunks_madvised) mozilla::DoublyLinkedList<arena_chunk_t>();
#endif
arena->spare = nullptr;
@ -5078,12 +5096,9 @@ hard_purge_arena(arena_t *arena)
{
malloc_spin_lock(&arena->lock);
while (!LinkedList_IsEmpty(&arena->chunks_madvised)) {
arena_chunk_t *chunk =
LinkedList_Get(arena->chunks_madvised.next,
arena_chunk_t, chunks_madvised_elem);
while (!arena->chunks_madvised.isEmpty()) {
arena_chunk_t *chunk = arena->chunks_madvised.popFront();
hard_purge_chunk(chunk);
LinkedList_Remove(&chunk->chunks_madvised_elem);
}
malloc_spin_unlock(&arena->lock);

View file

@ -365,6 +365,19 @@ public:
bool contains(const T& aElm) {
return find(aElm) != Iterator();
}
/**
* Returns whether the given element might be in the list. Note that this
* assumes the element is either in the list or not in the list, and ignores
* the case where the element might be in another list in order to make the
* check fast.
*/
bool ElementProbablyInList(T* aElm) {
if (isEmpty()) {
return false;
}
return !ElementNotInList(aElm);
}
};
} // namespace mozilla