forked from mirrors/gecko-dev
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:
parent
0d8ed2b1a5
commit
be1493b6fc
3 changed files with 42 additions and 89 deletions
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue