mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-03 02:25:34 +00:00
Bug 1413475 - Change comments to use C++ style // instead of /* */ in memory/build/. r=njn
--HG-- extra : rebase_source : 8d8b85e8123f414cb1e0e1eb067e0d198b3ebb8f
This commit is contained in:
parent
1de1ed32d0
commit
af14262e54
@ -4,13 +4,11 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Helper header to declare all the supported malloc functions.
|
||||
* MALLOC_DECL arguments are:
|
||||
* - function name
|
||||
* - return type
|
||||
* - argument types
|
||||
*/
|
||||
// Helper header to declare all the supported malloc functions.
|
||||
// MALLOC_DECL arguments are:
|
||||
// - function name
|
||||
// - return type
|
||||
// - argument types
|
||||
|
||||
#ifndef malloc_decls_h
|
||||
# define malloc_decls_h
|
||||
@ -32,7 +30,7 @@
|
||||
MALLOC_FUNCS_MALLOC | MALLOC_FUNCS_JEMALLOC | \
|
||||
MALLOC_FUNCS_ARENA)
|
||||
|
||||
#endif /* malloc_decls_h */
|
||||
#endif // malloc_decls_h
|
||||
|
||||
#ifndef MALLOC_FUNCS
|
||||
# define MALLOC_FUNCS (MALLOC_FUNCS_MALLOC | MALLOC_FUNCS_JEMALLOC | \
|
||||
@ -62,77 +60,65 @@ MALLOC_DECL(malloc_good_size, size_t, size_t)
|
||||
# endif
|
||||
# if MALLOC_FUNCS & MALLOC_FUNCS_JEMALLOC
|
||||
MALLOC_DECL(jemalloc_stats, void, jemalloc_stats_t *)
|
||||
/*
|
||||
* On some operating systems (Mac), we use madvise(MADV_FREE) to hand pages
|
||||
* back to the operating system. On Mac, the operating system doesn't take
|
||||
* this memory back immediately; instead, the OS takes it back only when the
|
||||
* machine is running out of physical memory.
|
||||
*
|
||||
* This is great from the standpoint of efficiency, but it makes measuring our
|
||||
* actual RSS difficult, because pages which we've MADV_FREE'd shouldn't count
|
||||
* against our RSS.
|
||||
*
|
||||
* This function explicitly purges any MADV_FREE'd pages from physical memory,
|
||||
* causing our reported RSS match the amount of memory we're actually using.
|
||||
*
|
||||
* Note that this call is expensive in two ways. First, it may be slow to
|
||||
* execute, because it may make a number of slow syscalls to free memory. This
|
||||
* function holds the big jemalloc locks, so basically all threads are blocked
|
||||
* while this function runs.
|
||||
*
|
||||
* This function is also expensive in that the next time we go to access a page
|
||||
* which we've just explicitly decommitted, the operating system has to attach
|
||||
* to it a physical page! If we hadn't run this function, the OS would have
|
||||
* less work to do.
|
||||
*
|
||||
* If MALLOC_DOUBLE_PURGE is not defined, this function does nothing.
|
||||
*/
|
||||
|
||||
// On some operating systems (Mac), we use madvise(MADV_FREE) to hand pages
|
||||
// back to the operating system. On Mac, the operating system doesn't take
|
||||
// this memory back immediately; instead, the OS takes it back only when the
|
||||
// machine is running out of physical memory.
|
||||
//
|
||||
// This is great from the standpoint of efficiency, but it makes measuring our
|
||||
// actual RSS difficult, because pages which we've MADV_FREE'd shouldn't count
|
||||
// against our RSS.
|
||||
//
|
||||
// This function explicitly purges any MADV_FREE'd pages from physical memory,
|
||||
// causing our reported RSS match the amount of memory we're actually using.
|
||||
//
|
||||
// Note that this call is expensive in two ways. First, it may be slow to
|
||||
// execute, because it may make a number of slow syscalls to free memory. This
|
||||
// function holds the big jemalloc locks, so basically all threads are blocked
|
||||
// while this function runs.
|
||||
//
|
||||
// This function is also expensive in that the next time we go to access a page
|
||||
// which we've just explicitly decommitted, the operating system has to attach
|
||||
// to it a physical page! If we hadn't run this function, the OS would have
|
||||
// less work to do.
|
||||
//
|
||||
// If MALLOC_DOUBLE_PURGE is not defined, this function does nothing.
|
||||
MALLOC_DECL(jemalloc_purge_freed_pages, void)
|
||||
|
||||
/*
|
||||
* Free all unused dirty pages in all arenas. Calling this function will slow
|
||||
* down subsequent allocations so it is recommended to use it only when
|
||||
* memory needs to be reclaimed at all costs (see bug 805855). This function
|
||||
* provides functionality similar to mallctl("arenas.purge") in jemalloc 3.
|
||||
*/
|
||||
// Free all unused dirty pages in all arenas. Calling this function will slow
|
||||
// down subsequent allocations so it is recommended to use it only when
|
||||
// memory needs to be reclaimed at all costs (see bug 805855). This function
|
||||
// provides functionality similar to mallctl("arenas.purge") in jemalloc 3.
|
||||
MALLOC_DECL(jemalloc_free_dirty_pages, void)
|
||||
|
||||
/*
|
||||
* Opt in or out of a thread local arena (bool argument is whether to opt-in
|
||||
* (true) or out (false)).
|
||||
*/
|
||||
// Opt in or out of a thread local arena (bool argument is whether to opt-in
|
||||
// (true) or out (false)).
|
||||
MALLOC_DECL(jemalloc_thread_local_arena, void, bool)
|
||||
|
||||
/*
|
||||
* Provide information about any allocation enclosing the given address.
|
||||
*/
|
||||
// Provide information about any allocation enclosing the given address.
|
||||
MALLOC_DECL(jemalloc_ptr_info, void, const void*, jemalloc_ptr_info_t*)
|
||||
# endif
|
||||
|
||||
# if MALLOC_FUNCS & MALLOC_FUNCS_ARENA_BASE
|
||||
/*
|
||||
* Creates a separate arena, and returns its id, valid to use with moz_arena_*
|
||||
* functions.
|
||||
*/
|
||||
|
||||
// Creates a separate arena, and returns its id, valid to use with moz_arena_*
|
||||
// functions.
|
||||
MALLOC_DECL(moz_create_arena, arena_id_t)
|
||||
|
||||
/*
|
||||
* Dispose of the given arena. Subsequent uses of the arena will fail.
|
||||
*/
|
||||
// Dispose of the given arena. Subsequent uses of the arena will fail.
|
||||
MALLOC_DECL(moz_dispose_arena, void, arena_id_t)
|
||||
# endif
|
||||
|
||||
# if MALLOC_FUNCS & MALLOC_FUNCS_ARENA_ALLOC
|
||||
/*
|
||||
* Same as the functions without the moz_arena_ prefix, but using arenas
|
||||
* created with moz_create_arena.
|
||||
* The contract, even if not enforced at runtime in some configurations,
|
||||
* is that moz_arena_realloc and moz_arena_free will crash if the wrong
|
||||
* arena id is given. All functions will crash if the arena id is invalid.
|
||||
* Although discouraged, plain realloc and free can still be used on
|
||||
* pointers allocated with these functions. Realloc will properly keep
|
||||
* new pointers in the same arena as the original.
|
||||
*/
|
||||
// Same as the functions without the moz_arena_ prefix, but using arenas
|
||||
// created with moz_create_arena.
|
||||
// The contract, even if not enforced at runtime in some configurations,
|
||||
// is that moz_arena_realloc and moz_arena_free will crash if the wrong
|
||||
// arena id is given. All functions will crash if the arena id is invalid.
|
||||
// Although discouraged, plain realloc and free can still be used on
|
||||
// pointers allocated with these functions. Realloc will properly keep
|
||||
// new pointers in the same arena as the original.
|
||||
MALLOC_DECL(moz_arena_malloc, void*, arena_id_t, size_t)
|
||||
MALLOC_DECL(moz_arena_calloc, void*, arena_id_t, size_t, size_t)
|
||||
MALLOC_DECL(moz_arena_realloc, void*, arena_id_t, void*, size_t)
|
||||
@ -140,7 +126,7 @@ MALLOC_DECL(moz_arena_free, void, arena_id_t, void*)
|
||||
MALLOC_DECL(moz_arena_memalign, void*, arena_id_t, size_t, size_t)
|
||||
# endif
|
||||
|
||||
#endif /* MALLOC_DECL */
|
||||
#endif // MALLOC_DECL
|
||||
|
||||
#undef MALLOC_DECL
|
||||
#undef MALLOC_FUNCS
|
||||
|
@ -10,10 +10,10 @@
|
||||
#include "mozjemalloc_types.h"
|
||||
#include "mozilla/MacroArgs.h"
|
||||
|
||||
/* Macro helpers */
|
||||
// Macro helpers
|
||||
|
||||
#define MACRO_CALL(a, b) a b
|
||||
/* Can't use macros recursively, so we need another one doing the same as above. */
|
||||
// Can't use macros recursively, so we need another one doing the same as above.
|
||||
#define MACRO_CALL2(a, b) a b
|
||||
|
||||
#define ARGS_HELPER(name, ...) MACRO_CALL2( \
|
||||
@ -31,10 +31,9 @@
|
||||
|
||||
#ifdef MOZ_MEMORY
|
||||
|
||||
/* Generic interface exposing the whole public allocator API
|
||||
* This facilitates the implementation of things like replace-malloc.
|
||||
* Note: compilers are expected to be able to optimize out `this`.
|
||||
*/
|
||||
// Generic interface exposing the whole public allocator API
|
||||
// This facilitates the implementation of things like replace-malloc.
|
||||
// Note: compilers are expected to be able to optimize out `this`.
|
||||
template <typename T>
|
||||
struct Allocator: public T {
|
||||
#define MALLOC_DECL(name, return_type, ...) \
|
||||
@ -42,12 +41,12 @@ struct Allocator: public T {
|
||||
#include "malloc_decls.h"
|
||||
};
|
||||
|
||||
/* The MozJemalloc allocator */
|
||||
// The MozJemalloc allocator
|
||||
struct MozJemallocBase {};
|
||||
typedef Allocator<MozJemallocBase> MozJemalloc;
|
||||
|
||||
#ifdef MOZ_REPLACE_MALLOC
|
||||
/* The replace-malloc allocator */
|
||||
// The replace-malloc allocator
|
||||
struct ReplaceMallocBase {};
|
||||
typedef Allocator<ReplaceMallocBase> ReplaceMalloc;
|
||||
|
||||
@ -56,10 +55,10 @@ typedef ReplaceMalloc DefaultMalloc;
|
||||
typedef MozJemalloc DefaultMalloc;
|
||||
#endif
|
||||
|
||||
#endif /* MOZ_MEMORY */
|
||||
#endif // MOZ_MEMORY
|
||||
|
||||
/* Dummy implementation of the moz_arena_* API, falling back to a given
|
||||
* implementation of the base allocator. */
|
||||
// Dummy implementation of the moz_arena_* API, falling back to a given
|
||||
// implementation of the base allocator.
|
||||
template <typename T>
|
||||
struct DummyArenaAllocator {
|
||||
static arena_id_t moz_create_arena(void) { return 0; }
|
||||
|
@ -4,40 +4,39 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* Portions of this file were originally under the following license:
|
||||
*
|
||||
* Copyright (C) 2006-2008 Jason Evans <jasone@FreeBSD.org>.
|
||||
* 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.
|
||||
*/
|
||||
// Portions of this file were originally under the following license:
|
||||
//
|
||||
// Copyright (C) 2006-2008 Jason Evans <jasone@FreeBSD.org>.
|
||||
// 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 _JEMALLOC_TYPES_H_
|
||||
#define _JEMALLOC_TYPES_H_
|
||||
|
||||
/* grab size_t */
|
||||
// grab size_t
|
||||
#ifdef _MSC_VER
|
||||
#include <crtdefs.h>
|
||||
#else
|
||||
@ -57,38 +56,32 @@ typedef MALLOC_USABLE_SIZE_CONST_PTR void* usable_ptr_t;
|
||||
|
||||
typedef size_t arena_id_t;
|
||||
|
||||
/*
|
||||
* jemalloc_stats() is not a stable interface. When using jemalloc_stats_t, be
|
||||
* sure that the compiled results of jemalloc.c are in sync with this header
|
||||
* file.
|
||||
*/
|
||||
// jemalloc_stats() is not a stable interface. When using jemalloc_stats_t, be
|
||||
// sure that the compiled results of jemalloc.c are in sync with this header
|
||||
// file.
|
||||
typedef struct {
|
||||
/*
|
||||
* Run-time configuration settings.
|
||||
*/
|
||||
bool opt_junk; /* Fill allocated memory with kAllocJunk? */
|
||||
bool opt_zero; /* Fill allocated memory with 0x0? */
|
||||
size_t narenas; /* Number of arenas. */
|
||||
size_t quantum; /* Allocation quantum. */
|
||||
size_t small_max; /* Max quantum-spaced allocation size. */
|
||||
size_t large_max; /* Max sub-chunksize allocation size. */
|
||||
size_t chunksize; /* Size of each virtual memory mapping. */
|
||||
size_t page_size; /* Size of pages. */
|
||||
size_t dirty_max; /* Max dirty pages per arena. */
|
||||
// Run-time configuration settings.
|
||||
bool opt_junk; // Fill allocated memory with kAllocJunk?
|
||||
bool opt_zero; // Fill allocated memory with 0x0?
|
||||
size_t narenas; // Number of arenas.
|
||||
size_t quantum; // Allocation quantum.
|
||||
size_t small_max; // Max quantum-spaced allocation size.
|
||||
size_t large_max; // Max sub-chunksize allocation size.
|
||||
size_t chunksize; // Size of each virtual memory mapping.
|
||||
size_t page_size; // Size of pages.
|
||||
size_t dirty_max; // Max dirty pages per arena.
|
||||
|
||||
/*
|
||||
* Current memory usage statistics.
|
||||
*/
|
||||
size_t mapped; /* Bytes mapped (not necessarily committed). */
|
||||
size_t allocated; /* Bytes allocated (committed, in use by application). */
|
||||
size_t waste; /* Bytes committed, not in use by the
|
||||
application, and not intentionally left
|
||||
unused (i.e., not dirty). */
|
||||
size_t page_cache; /* Committed, unused pages kept around as a
|
||||
cache. (jemalloc calls these "dirty".) */
|
||||
size_t bookkeeping; /* Committed bytes used internally by the
|
||||
allocator. */
|
||||
size_t bin_unused; /* Bytes committed to a bin but currently unused. */
|
||||
// Current memory usage statistics.
|
||||
size_t mapped; // Bytes mapped (not necessarily committed).
|
||||
size_t allocated; // Bytes allocated (committed, in use by application).
|
||||
size_t waste; // Bytes committed, not in use by the
|
||||
// application, and not intentionally left
|
||||
// unused (i.e., not dirty).
|
||||
size_t page_cache; // Committed, unused pages kept around as a
|
||||
// cache. (jemalloc calls these "dirty".)
|
||||
size_t bookkeeping; // Committed bytes used internally by the
|
||||
// allocator.
|
||||
size_t bin_unused; // Bytes committed to a bin but currently unused.
|
||||
} jemalloc_stats_t;
|
||||
|
||||
enum PtrInfoTag {
|
||||
@ -115,13 +108,11 @@ enum PtrInfoTag {
|
||||
TagFreedPageZeroed,
|
||||
};
|
||||
|
||||
/*
|
||||
* The information in jemalloc_ptr_info_t could be represented in a variety of
|
||||
* ways. The chosen representation has the following properties.
|
||||
* - The number of fields is minimized.
|
||||
* - The 'tag' field unambiguously defines the meaning of the subsequent fields.
|
||||
* Helper functions are used to group together related categories of tags.
|
||||
*/
|
||||
// The information in jemalloc_ptr_info_t could be represented in a variety of
|
||||
// ways. The chosen representation has the following properties.
|
||||
// - The number of fields is minimized.
|
||||
// - The 'tag' field unambiguously defines the meaning of the subsequent fields.
|
||||
// Helper functions are used to group together related categories of tags.
|
||||
typedef struct {
|
||||
enum PtrInfoTag tag;
|
||||
void* addr; // meaning depends on tag; see above
|
||||
@ -156,7 +147,7 @@ jemalloc_ptr_is_freed_page(jemalloc_ptr_info_t* info)
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif /* _JEMALLOC_TYPES_H_ */
|
||||
#endif // _JEMALLOC_TYPES_H_
|
||||
|
@ -7,16 +7,14 @@
|
||||
#ifndef mozmemory_h
|
||||
#define mozmemory_h
|
||||
|
||||
/*
|
||||
* This header is meant to be used when the following functions are
|
||||
* necessary:
|
||||
* - malloc_good_size (used to be called je_malloc_usable_in_advance)
|
||||
* - jemalloc_stats
|
||||
* - jemalloc_purge_freed_pages
|
||||
* - jemalloc_free_dirty_pages
|
||||
* - jemalloc_thread_local_arena
|
||||
* - jemalloc_ptr_info
|
||||
*/
|
||||
// This header is meant to be used when the following functions are
|
||||
// necessary:
|
||||
// - malloc_good_size (used to be called je_malloc_usable_in_advance)
|
||||
// - jemalloc_stats
|
||||
// - jemalloc_purge_freed_pages
|
||||
// - jemalloc_free_dirty_pages
|
||||
// - jemalloc_thread_local_arena
|
||||
// - jemalloc_ptr_info
|
||||
|
||||
#ifdef MALLOC_H
|
||||
#include MALLOC_H
|
||||
@ -27,17 +25,14 @@
|
||||
#include "mozjemalloc_types.h"
|
||||
|
||||
#ifdef MOZ_MEMORY
|
||||
/*
|
||||
* On OSX, malloc/malloc.h contains the declaration for malloc_good_size,
|
||||
* which will call back in jemalloc, through the zone allocator so just use it.
|
||||
*/
|
||||
// On OSX, malloc/malloc.h contains the declaration for malloc_good_size,
|
||||
// which will call back in jemalloc, through the zone allocator so just use it.
|
||||
#ifndef XP_DARWIN
|
||||
MOZ_MEMORY_API size_t malloc_good_size_impl(size_t size);
|
||||
|
||||
/* Note: the MOZ_GLUE_IN_PROGRAM ifdef below is there to avoid -Werror turning
|
||||
* the protective if into errors. MOZ_GLUE_IN_PROGRAM is what triggers MFBT_API
|
||||
* to use weak imports. */
|
||||
|
||||
// Note: the MOZ_GLUE_IN_PROGRAM ifdef below is there to avoid -Werror turning
|
||||
// the protective if into errors. MOZ_GLUE_IN_PROGRAM is what triggers MFBT_API
|
||||
// to use weak imports.
|
||||
static inline size_t _malloc_good_size(size_t size) {
|
||||
# if defined(MOZ_GLUE_IN_PROGRAM) && !defined(IMPL_MFBT)
|
||||
if (!malloc_good_size)
|
||||
@ -61,4 +56,4 @@ static inline size_t _malloc_good_size(size_t size) {
|
||||
#define MALLOC_FUNCS MALLOC_FUNCS_ARENA
|
||||
#include "malloc_decls.h"
|
||||
|
||||
#endif /* mozmemory_h */
|
||||
#endif // mozmemory_h
|
||||
|
@ -8,8 +8,8 @@
|
||||
#include "mozmemory_wrap.h"
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
/* Declare malloc implementation functions with the right return and
|
||||
* argument types. */
|
||||
// Declare malloc implementation functions with the right return and
|
||||
// argument types.
|
||||
#define MALLOC_DECL(name, return_type, ...) \
|
||||
MOZ_MEMORY_API return_type name ## _impl(__VA_ARGS__);
|
||||
#define MALLOC_FUNCS MALLOC_FUNCS_MALLOC
|
||||
@ -67,8 +67,8 @@ operator delete[](void* ptr, std::nothrow_t const&)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* strndup and strdup may be defined as macros in string.h, which would
|
||||
* clash with the definitions below. */
|
||||
// strndup and strdup may be defined as macros in string.h, which would
|
||||
// clash with the definitions below.
|
||||
#undef strndup
|
||||
#undef strdup
|
||||
|
||||
@ -147,10 +147,8 @@ asprintf_impl(char **str, const char *fmt, ...)
|
||||
#ifdef XP_WIN
|
||||
#include <wchar.h>
|
||||
|
||||
/*
|
||||
* We also need to provide our own impl of wcsdup so that we don't ask
|
||||
* the CRT for memory from its heap (which will then be unfreeable).
|
||||
*/
|
||||
// We also need to provide our own impl of wcsdup so that we don't ask
|
||||
// the CRT for memory from its heap (which will then be unfreeable).
|
||||
MOZ_MEMORY_API wchar_t*
|
||||
wcsdup_impl(const wchar_t* src)
|
||||
{
|
||||
@ -166,4 +164,4 @@ _aligned_malloc(size_t size, size_t alignment)
|
||||
{
|
||||
return memalign_impl(alignment, size);
|
||||
}
|
||||
#endif /* XP_WIN */
|
||||
#endif // XP_WIN
|
||||
|
@ -7,91 +7,89 @@
|
||||
#ifndef mozmemory_wrap_h
|
||||
#define mozmemory_wrap_h
|
||||
|
||||
/*
|
||||
* This header contains #defines which tweak the names of various memory
|
||||
* allocation functions.
|
||||
*
|
||||
* There are several types of functions related to memory allocation
|
||||
* that are meant to be used publicly by the Gecko codebase:
|
||||
*
|
||||
* - malloc implementation functions:
|
||||
* - malloc
|
||||
* - posix_memalign
|
||||
* - aligned_alloc
|
||||
* - calloc
|
||||
* - realloc
|
||||
* - free
|
||||
* - memalign
|
||||
* - valloc
|
||||
* - malloc_usable_size
|
||||
* - malloc_good_size
|
||||
* Some of these functions are specific to some systems, but for
|
||||
* convenience, they are treated as being cross-platform, and available
|
||||
* as such.
|
||||
*
|
||||
* - duplication functions:
|
||||
* - strndup
|
||||
* - strdup
|
||||
* - wcsdup (Windows only)
|
||||
*
|
||||
* - jemalloc specific functions:
|
||||
* - jemalloc_stats
|
||||
* - jemalloc_purge_freed_pages
|
||||
* - jemalloc_free_dirty_pages
|
||||
* - jemalloc_thread_local_arena
|
||||
* - jemalloc_ptr_info
|
||||
* (these functions are native to mozjemalloc)
|
||||
*
|
||||
* These functions are all exported as part of libmozglue (see
|
||||
* $(topsrcdir)/mozglue/build/Makefile.in), with a few implementation
|
||||
* peculiarities:
|
||||
*
|
||||
* - On Windows, the malloc implementation functions are all prefixed with
|
||||
* "je_", the duplication functions are prefixed with "wrap_", and jemalloc
|
||||
* specific functions are left unprefixed. All these functions are however
|
||||
* aliased when exporting them, such that the resulting mozglue.dll exports
|
||||
* them unprefixed (see $(topsrcdir)/mozglue/build/mozglue.def.in). The
|
||||
* prefixed malloc implementation and duplication functions are not
|
||||
* exported.
|
||||
*
|
||||
* - On MacOSX, the system libc has a zone allocator, which allows us to
|
||||
* hook custom malloc implementation functions without exporting them.
|
||||
* However, since we want things in Firefox to skip the system zone
|
||||
* allocator, the malloc implementation functions are all exported
|
||||
* unprefixed, as well as duplication functions.
|
||||
* Jemalloc-specific functions are also left unprefixed.
|
||||
*
|
||||
* - On Android all functions are left unprefixed. Additionally,
|
||||
* C++ allocation functions (operator new/delete) are also exported and
|
||||
* unprefixed.
|
||||
*
|
||||
* - On other systems (mostly Linux), all functions are left unprefixed.
|
||||
*
|
||||
* Only Android adds C++ allocation functions.
|
||||
*
|
||||
* Proper exporting of the various functions is done with the MOZ_MEMORY_API
|
||||
* and MOZ_JEMALLOC_API macros. MOZ_MEMORY_API is meant to be used for malloc
|
||||
* implementation and duplication functions, while MOZ_JEMALLOC_API is
|
||||
* dedicated to jemalloc specific functions.
|
||||
*
|
||||
*
|
||||
* All these functions are meant to be called with no prefix from Gecko code.
|
||||
* In most cases, this is because that's how they are available at runtime.
|
||||
* However, on Android, this relies on faulty.lib (the custom dynamic linker)
|
||||
* resolving mozglue symbols before libc symbols, which is guaranteed by the
|
||||
* way faulty.lib works (it respects the DT_NEEDED order, and libc always
|
||||
* appears after mozglue ; which we double check when building anyways)
|
||||
*
|
||||
*
|
||||
* Within libmozglue (when MOZ_MEMORY_IMPL is defined), all the functions
|
||||
* should be suffixed with "_impl" both for declarations and use.
|
||||
* That is, the implementation declaration for e.g. strdup would look like:
|
||||
* char* strdup_impl(const char *)
|
||||
* That implementation would call malloc by using "malloc_impl".
|
||||
*/
|
||||
// This header contains #defines which tweak the names of various memory
|
||||
// allocation functions.
|
||||
//
|
||||
// There are several types of functions related to memory allocation
|
||||
// that are meant to be used publicly by the Gecko codebase:
|
||||
//
|
||||
// - malloc implementation functions:
|
||||
// - malloc
|
||||
// - posix_memalign
|
||||
// - aligned_alloc
|
||||
// - calloc
|
||||
// - realloc
|
||||
// - free
|
||||
// - memalign
|
||||
// - valloc
|
||||
// - malloc_usable_size
|
||||
// - malloc_good_size
|
||||
// Some of these functions are specific to some systems, but for
|
||||
// convenience, they are treated as being cross-platform, and available
|
||||
// as such.
|
||||
//
|
||||
// - duplication functions:
|
||||
// - strndup
|
||||
// - strdup
|
||||
// - wcsdup (Windows only)
|
||||
//
|
||||
// - jemalloc specific functions:
|
||||
// - jemalloc_stats
|
||||
// - jemalloc_purge_freed_pages
|
||||
// - jemalloc_free_dirty_pages
|
||||
// - jemalloc_thread_local_arena
|
||||
// - jemalloc_ptr_info
|
||||
// (these functions are native to mozjemalloc)
|
||||
//
|
||||
// These functions are all exported as part of libmozglue (see
|
||||
// $(topsrcdir)/mozglue/build/Makefile.in), with a few implementation
|
||||
// peculiarities:
|
||||
//
|
||||
// - On Windows, the malloc implementation functions are all prefixed with
|
||||
// "je_", the duplication functions are prefixed with "wrap_", and jemalloc
|
||||
// specific functions are left unprefixed. All these functions are however
|
||||
// aliased when exporting them, such that the resulting mozglue.dll exports
|
||||
// them unprefixed (see $(topsrcdir)/mozglue/build/mozglue.def.in). The
|
||||
// prefixed malloc implementation and duplication functions are not
|
||||
// exported.
|
||||
//
|
||||
// - On MacOSX, the system libc has a zone allocator, which allows us to
|
||||
// hook custom malloc implementation functions without exporting them.
|
||||
// However, since we want things in Firefox to skip the system zone
|
||||
// allocator, the malloc implementation functions are all exported
|
||||
// unprefixed, as well as duplication functions.
|
||||
// Jemalloc-specific functions are also left unprefixed.
|
||||
//
|
||||
// - On Android all functions are left unprefixed. Additionally,
|
||||
// C++ allocation functions (operator new/delete) are also exported and
|
||||
// unprefixed.
|
||||
//
|
||||
// - On other systems (mostly Linux), all functions are left unprefixed.
|
||||
//
|
||||
// Only Android adds C++ allocation functions.
|
||||
//
|
||||
// Proper exporting of the various functions is done with the MOZ_MEMORY_API
|
||||
// and MOZ_JEMALLOC_API macros. MOZ_MEMORY_API is meant to be used for malloc
|
||||
// implementation and duplication functions, while MOZ_JEMALLOC_API is
|
||||
// dedicated to jemalloc specific functions.
|
||||
//
|
||||
//
|
||||
// All these functions are meant to be called with no prefix from Gecko code.
|
||||
// In most cases, this is because that's how they are available at runtime.
|
||||
// However, on Android, this relies on faulty.lib (the custom dynamic linker)
|
||||
// resolving mozglue symbols before libc symbols, which is guaranteed by the
|
||||
// way faulty.lib works (it respects the DT_NEEDED order, and libc always
|
||||
// appears after mozglue ; which we double check when building anyways)
|
||||
//
|
||||
//
|
||||
// Within libmozglue (when MOZ_MEMORY_IMPL is defined), all the functions
|
||||
// should be suffixed with "_impl" both for declarations and use.
|
||||
// That is, the implementation declaration for e.g. strdup would look like:
|
||||
// char* strdup_impl(const char *)
|
||||
// That implementation would call malloc by using "malloc_impl".
|
||||
|
||||
#if defined(MOZ_MEMORY_IMPL) && !defined(IMPL_MFBT)
|
||||
# ifdef MFBT_API /* mozilla/Types.h was already included */
|
||||
# ifdef MFBT_API // mozilla/Types.h was already included
|
||||
# error mozmemory_wrap.h has to be included before mozilla/Types.h when MOZ_MEMORY_IMPL is set and IMPL_MFBT is not.
|
||||
# endif
|
||||
# define IMPL_MFBT
|
||||
@ -141,7 +139,7 @@
|
||||
# define mozmem_dup_impl(a) a
|
||||
#endif
|
||||
|
||||
/* Malloc implementation functions */
|
||||
// Malloc implementation functions
|
||||
#define malloc_impl mozmem_malloc_impl(malloc)
|
||||
#define posix_memalign_impl mozmem_malloc_impl(posix_memalign)
|
||||
#define aligned_alloc_impl mozmem_malloc_impl(aligned_alloc)
|
||||
@ -153,20 +151,19 @@
|
||||
#define malloc_usable_size_impl mozmem_malloc_impl(malloc_usable_size)
|
||||
#define malloc_good_size_impl mozmem_malloc_impl(malloc_good_size)
|
||||
|
||||
/* Duplication functions */
|
||||
// Duplication functions
|
||||
#define strndup_impl mozmem_dup_impl(strndup)
|
||||
#define strdup_impl mozmem_dup_impl(strdup)
|
||||
#ifdef XP_WIN
|
||||
# define wcsdup_impl mozmem_dup_impl(wcsdup)
|
||||
#endif
|
||||
|
||||
/* String functions */
|
||||
// String functions
|
||||
#ifdef ANDROID
|
||||
/* Bug 801571 and Bug 879668, libstagefright uses vasprintf, causing malloc()/
|
||||
* free() to be mismatched between bionic and mozglue implementation.
|
||||
*/
|
||||
// Bug 801571 and Bug 879668, libstagefright uses vasprintf, causing malloc()/
|
||||
// free() to be mismatched between bionic and mozglue implementation.
|
||||
#define vasprintf_impl mozmem_dup_impl(vasprintf)
|
||||
#define asprintf_impl mozmem_dup_impl(asprintf)
|
||||
#endif
|
||||
|
||||
#endif /* mozmemory_wrap_h */
|
||||
#endif // mozmemory_wrap_h
|
||||
|
@ -4,65 +4,64 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/*
|
||||
* Portions of this file were originally under the following license:
|
||||
*
|
||||
* Copyright (C) 2008 Jason Evans <jasone@FreeBSD.org>.
|
||||
* 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
|
||||
* unmodified other than the allowable 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.
|
||||
*
|
||||
******************************************************************************
|
||||
*
|
||||
* C++ template implementation of left-leaning red-black trees.
|
||||
*
|
||||
* All operations are done non-recursively. Parent pointers are not used, and
|
||||
* color bits are stored in the least significant bit of right-child pointers,
|
||||
* thus making node linkage as compact as is possible for red-black trees.
|
||||
*
|
||||
* The RedBlackTree template expects two type arguments: the type of the nodes,
|
||||
* containing a RedBlackTreeNode, and a trait providing two methods:
|
||||
* - a GetTreeNode method that returns a reference to the RedBlackTreeNode
|
||||
* corresponding to a given node with the following signature:
|
||||
* static RedBlackTreeNode<T>& GetTreeNode(T*)
|
||||
* - a Compare function with the following signature:
|
||||
* static int Compare(T* aNode, T* aOther)
|
||||
* ^^^^^
|
||||
* or aKey
|
||||
*
|
||||
* Interpretation of comparision function return values:
|
||||
*
|
||||
* -1 : aNode < aOther
|
||||
* 0 : aNode == aOther
|
||||
* 1 : aNode > aOther
|
||||
*
|
||||
* In all cases, the aNode or aKey argument is the first argument to the
|
||||
* comparison function, which makes it possible to write comparison functions
|
||||
* that treat the first argument specially.
|
||||
*
|
||||
******************************************************************************/
|
||||
// Portions of this file were originally under the following license:
|
||||
//
|
||||
// Copyright (C) 2008 Jason Evans <jasone@FreeBSD.org>.
|
||||
// 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
|
||||
// unmodified other than the allowable 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.
|
||||
//
|
||||
// ****************************************************************************
|
||||
//
|
||||
// C++ template implementation of left-leaning red-black trees.
|
||||
//
|
||||
// All operations are done non-recursively. Parent pointers are not used, and
|
||||
// color bits are stored in the least significant bit of right-child pointers,
|
||||
// thus making node linkage as compact as is possible for red-black trees.
|
||||
//
|
||||
// The RedBlackTree template expects two type arguments: the type of the nodes,
|
||||
// containing a RedBlackTreeNode, and a trait providing two methods:
|
||||
// - a GetTreeNode method that returns a reference to the RedBlackTreeNode
|
||||
// corresponding to a given node with the following signature:
|
||||
// static RedBlackTreeNode<T>& GetTreeNode(T*)
|
||||
// - a Compare function with the following signature:
|
||||
// static int Compare(T* aNode, T* aOther)
|
||||
// ^^^^^
|
||||
// or aKey
|
||||
//
|
||||
// Interpretation of comparision function return values:
|
||||
//
|
||||
// -1 : aNode < aOther
|
||||
// 0 : aNode == aOther
|
||||
// 1 : aNode > aOther
|
||||
//
|
||||
// In all cases, the aNode or aKey argument is the first argument to the
|
||||
// comparison function, which makes it possible to write comparison functions
|
||||
// that treat the first argument specially.
|
||||
//
|
||||
// ***************************************************************************
|
||||
|
||||
#ifndef RB_H_
|
||||
#define RB_H_
|
||||
@ -76,12 +75,12 @@ enum NodeColor
|
||||
Red = 1,
|
||||
};
|
||||
|
||||
/* Node structure. */
|
||||
// Node structure.
|
||||
template <typename T>
|
||||
class RedBlackTreeNode
|
||||
{
|
||||
T* mLeft;
|
||||
/* The lowest bit is the color */
|
||||
// The lowest bit is the color
|
||||
T* mRightAndColor;
|
||||
|
||||
public:
|
||||
@ -129,7 +128,7 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/* Tree structure. */
|
||||
// Tree structure.
|
||||
template<typename T, typename Trait>
|
||||
class RedBlackTree
|
||||
{
|
||||
@ -161,8 +160,8 @@ public:
|
||||
return Search(reinterpret_cast<TreeNode*>(aKey));
|
||||
}
|
||||
|
||||
/* Find a match if it exists. Otherwise, find the next greater node, if one
|
||||
* exists */
|
||||
// Find a match if it exists. Otherwise, find the next greater node, if one
|
||||
// exists.
|
||||
T* SearchOrNext(T* aKey)
|
||||
{
|
||||
return SearchOrNext(reinterpret_cast<TreeNode*>(aKey));
|
||||
@ -178,8 +177,8 @@ public:
|
||||
return Remove(reinterpret_cast<TreeNode*>(aNode));
|
||||
}
|
||||
|
||||
/* Helper class to avoid having all the tree traversal code further below
|
||||
* have to use Trait::GetTreeNode, adding visual noise. */
|
||||
// Helper class to avoid having all the tree traversal code further below
|
||||
// have to use Trait::GetTreeNode, adding visual noise.
|
||||
struct TreeNode : public T
|
||||
{
|
||||
TreeNode* Left()
|
||||
@ -339,29 +338,29 @@ private:
|
||||
rbp_i_p->SetRight(nullptr);
|
||||
rbp_i_p->SetColor(NodeColor::Black);
|
||||
rbp_i_c = mRoot;
|
||||
/* Iteratively search down the tree for the insertion point,
|
||||
* splitting 4-nodes as they are encountered. At the end of each
|
||||
* iteration, rbp_i_g->rbp_i_p->rbp_i_c is a 3-level path down
|
||||
* the tree, assuming a sufficiently deep tree. */
|
||||
// Iteratively search down the tree for the insertion point,
|
||||
// splitting 4-nodes as they are encountered. At the end of each
|
||||
// iteration, rbp_i_g->rbp_i_p->rbp_i_c is a 3-level path down
|
||||
// the tree, assuming a sufficiently deep tree.
|
||||
while (rbp_i_c) {
|
||||
rbp_i_t = rbp_i_c->Left();
|
||||
rbp_i_u = rbp_i_t ? rbp_i_t->Left() : nullptr;
|
||||
if (rbp_i_t && rbp_i_u && rbp_i_t->IsRed() && rbp_i_u->IsRed()) {
|
||||
/* rbp_i_c is the top of a logical 4-node, so split it.
|
||||
* This iteration does not move down the tree, due to the
|
||||
* disruptiveness of node splitting.
|
||||
*
|
||||
* Rotate right. */
|
||||
// rbp_i_c is the top of a logical 4-node, so split it.
|
||||
// This iteration does not move down the tree, due to the
|
||||
// disruptiveness of node splitting.
|
||||
//
|
||||
// Rotate right.
|
||||
rbp_i_t = RotateRight(rbp_i_c);
|
||||
/* Pass red links up one level. */
|
||||
// Pass red links up one level.
|
||||
rbp_i_u = rbp_i_t->Left();
|
||||
rbp_i_u->SetColor(NodeColor::Black);
|
||||
if (rbp_i_p->Left() == rbp_i_c) {
|
||||
rbp_i_p->SetLeft(rbp_i_t);
|
||||
rbp_i_c = rbp_i_t;
|
||||
} else {
|
||||
/* rbp_i_c was the right child of rbp_i_p, so rotate
|
||||
* left in order to maintain the left-leaning invariant. */
|
||||
// rbp_i_c was the right child of rbp_i_p, so rotate
|
||||
// left in order to maintain the left-leaning invariant.
|
||||
MOZ_ASSERT(rbp_i_p->Right() == rbp_i_c);
|
||||
rbp_i_p->SetRight(rbp_i_t);
|
||||
rbp_i_u = LeanLeft(rbp_i_p);
|
||||
@ -392,7 +391,7 @@ private:
|
||||
rbp_i_c = rbp_i_c->Right();
|
||||
}
|
||||
}
|
||||
/* rbp_i_p now refers to the node under which to insert. */
|
||||
// rbp_i_p now refers to the node under which to insert.
|
||||
aNode->SetLeft(nullptr);
|
||||
aNode->SetRight(nullptr);
|
||||
aNode->SetColor(NodeColor::Red);
|
||||
@ -407,7 +406,7 @@ private:
|
||||
} else {
|
||||
rbp_i_p->SetLeft(aNode);
|
||||
}
|
||||
/* Update the root and make sure that it is black. */
|
||||
// Update the root and make sure that it is black.
|
||||
mRoot = rbp_i_s.addr()->Left();
|
||||
mRoot->SetColor(NodeColor::Black);
|
||||
}
|
||||
@ -425,24 +424,24 @@ private:
|
||||
rbp_r_p->SetColor(NodeColor::Black);
|
||||
rbp_r_c = mRoot;
|
||||
rbp_r_xp = nullptr;
|
||||
/* Iterate down the tree, but always transform 2-nodes to 3- or
|
||||
* 4-nodes in order to maintain the invariant that the current
|
||||
* node is not a 2-node. This allows simple deletion once a leaf
|
||||
* is reached. Handle the root specially though, since there may
|
||||
* be no way to convert it from a 2-node to a 3-node. */
|
||||
// Iterate down the tree, but always transform 2-nodes to 3- or
|
||||
// 4-nodes in order to maintain the invariant that the current
|
||||
// node is not a 2-node. This allows simple deletion once a leaf
|
||||
// is reached. Handle the root specially though, since there may
|
||||
// be no way to convert it from a 2-node to a 3-node.
|
||||
rbp_r_cmp = Trait::Compare(aNode, rbp_r_c);
|
||||
if (rbp_r_cmp < 0) {
|
||||
rbp_r_t = rbp_r_c->Left();
|
||||
rbp_r_u = rbp_r_t ? rbp_r_t->Left() : nullptr;
|
||||
if ((!rbp_r_t || rbp_r_t->IsBlack()) &&
|
||||
(!rbp_r_u || rbp_r_u->IsBlack())) {
|
||||
/* Apply standard transform to prepare for left move. */
|
||||
// Apply standard transform to prepare for left move.
|
||||
rbp_r_t = MoveRedLeft(rbp_r_c);
|
||||
rbp_r_t->SetColor(NodeColor::Black);
|
||||
rbp_r_p->SetLeft(rbp_r_t);
|
||||
rbp_r_c = rbp_r_t;
|
||||
} else {
|
||||
/* Move left. */
|
||||
// Move left.
|
||||
rbp_r_p = rbp_r_c;
|
||||
rbp_r_c = rbp_r_c->Left();
|
||||
}
|
||||
@ -450,7 +449,7 @@ private:
|
||||
if (rbp_r_cmp == 0) {
|
||||
MOZ_ASSERT(aNode == rbp_r_c);
|
||||
if (!rbp_r_c->Right()) {
|
||||
/* Delete root node (which is also a leaf node). */
|
||||
// Delete root node (which is also a leaf node).
|
||||
if (rbp_r_c->Left()) {
|
||||
rbp_r_t = LeanRight(rbp_r_c);
|
||||
rbp_r_t->SetRight(nullptr);
|
||||
@ -459,12 +458,12 @@ private:
|
||||
}
|
||||
rbp_r_p->SetLeft(rbp_r_t);
|
||||
} else {
|
||||
/* This is the node we want to delete, but we will
|
||||
* instead swap it with its successor and delete the
|
||||
* successor. Record enough information to do the
|
||||
* swap later. rbp_r_xp is the aNode's parent. */
|
||||
// This is the node we want to delete, but we will
|
||||
// instead swap it with its successor and delete the
|
||||
// successor. Record enough information to do the
|
||||
// swap later. rbp_r_xp is the aNode's parent.
|
||||
rbp_r_xp = rbp_r_p;
|
||||
rbp_r_cmp = 1; /* Note that deletion is incomplete. */
|
||||
rbp_r_cmp = 1; // Note that deletion is incomplete.
|
||||
}
|
||||
}
|
||||
if (rbp_r_cmp == 1) {
|
||||
@ -472,10 +471,10 @@ private:
|
||||
rbp_r_c->Right()->Left()->IsBlack())) {
|
||||
rbp_r_t = rbp_r_c->Left();
|
||||
if (rbp_r_t->IsRed()) {
|
||||
/* Standard transform. */
|
||||
// Standard transform.
|
||||
rbp_r_t = MoveRedRight(rbp_r_c);
|
||||
} else {
|
||||
/* Root-specific transform. */
|
||||
// Root-specific transform.
|
||||
rbp_r_c->SetColor(NodeColor::Red);
|
||||
rbp_r_u = rbp_r_t->Left();
|
||||
if (rbp_r_u && rbp_r_u->IsRed()) {
|
||||
@ -491,7 +490,7 @@ private:
|
||||
rbp_r_p->SetLeft(rbp_r_t);
|
||||
rbp_r_c = rbp_r_t;
|
||||
} else {
|
||||
/* Move right. */
|
||||
// Move right.
|
||||
rbp_r_p = rbp_r_c;
|
||||
rbp_r_c = rbp_r_c->Right();
|
||||
}
|
||||
@ -504,9 +503,9 @@ private:
|
||||
if (rbp_r_cmp < 0) {
|
||||
rbp_r_t = rbp_r_c->Left();
|
||||
if (!rbp_r_t) {
|
||||
/* rbp_r_c now refers to the successor node to
|
||||
* relocate, and rbp_r_xp/aNode refer to the
|
||||
* context for the relocation. */
|
||||
// rbp_r_c now refers to the successor node to
|
||||
// relocate, and rbp_r_xp/aNode refer to the
|
||||
// context for the relocation.
|
||||
if (rbp_r_xp->Left() == aNode) {
|
||||
rbp_r_xp->SetLeft(rbp_r_c);
|
||||
} else {
|
||||
@ -538,12 +537,12 @@ private:
|
||||
rbp_r_c = rbp_r_c->Left();
|
||||
}
|
||||
} else {
|
||||
/* Check whether to delete this node (it has to be
|
||||
* the correct node and a leaf node). */
|
||||
// Check whether to delete this node (it has to be
|
||||
// the correct node and a leaf node).
|
||||
if (rbp_r_cmp == 0) {
|
||||
MOZ_ASSERT(aNode == rbp_r_c);
|
||||
if (!rbp_r_c->Right()) {
|
||||
/* Delete leaf node. */
|
||||
// Delete leaf node.
|
||||
if (rbp_r_c->Left()) {
|
||||
rbp_r_t = LeanRight(rbp_r_c);
|
||||
rbp_r_t->SetRight(nullptr);
|
||||
@ -557,11 +556,11 @@ private:
|
||||
}
|
||||
break;
|
||||
}
|
||||
/* This is the node we want to delete, but we
|
||||
* will instead swap it with its successor
|
||||
* and delete the successor. Record enough
|
||||
* information to do the swap later.
|
||||
* rbp_r_xp is aNode's parent. */
|
||||
// This is the node we want to delete, but we
|
||||
// will instead swap it with its successor
|
||||
// and delete the successor. Record enough
|
||||
// information to do the swap later.
|
||||
// rbp_r_xp is aNode's parent.
|
||||
rbp_r_xp = rbp_r_p;
|
||||
}
|
||||
rbp_r_t = rbp_r_c->Right();
|
||||
@ -581,7 +580,7 @@ private:
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Update root. */
|
||||
// Update root.
|
||||
mRoot = rbp_r_s.addr()->Left();
|
||||
}
|
||||
|
||||
@ -687,32 +686,29 @@ private:
|
||||
return node;
|
||||
}
|
||||
|
||||
/*
|
||||
* The iterator simulates recursion via an array of pointers that store the
|
||||
* current path. This is critical to performance, since a series of calls to
|
||||
* rb_{next,prev}() would require time proportional to (n lg n), whereas this
|
||||
* implementation only requires time proportional to (n).
|
||||
*
|
||||
* Since the iterator caches a path down the tree, any tree modification may
|
||||
* cause the cached path to become invalid. Don't modify the tree during an
|
||||
* iteration.
|
||||
*/
|
||||
// The iterator simulates recursion via an array of pointers that store the
|
||||
// current path. This is critical to performance, since a series of calls to
|
||||
// rb_{next,prev}() would require time proportional to (n lg n), whereas this
|
||||
// implementation only requires time proportional to (n).
|
||||
//
|
||||
// Since the iterator caches a path down the tree, any tree modification may
|
||||
// cause the cached path to become invalid. Don't modify the tree during an
|
||||
// iteration.
|
||||
|
||||
/*
|
||||
* Size the path arrays such that they are always large enough, even if a
|
||||
* tree consumes all of memory. Since each node must contain a minimum of
|
||||
* two pointers, there can never be more nodes than:
|
||||
*
|
||||
* 1 << ((sizeof(void*)<<3) - (log2(sizeof(void*))+1))
|
||||
*
|
||||
* Since the depth of a tree is limited to 3*lg(#nodes), the maximum depth
|
||||
* is:
|
||||
*
|
||||
* (3 * ((sizeof(void*)<<3) - (log2(sizeof(void*))+1)))
|
||||
*
|
||||
* This works out to a maximum depth of 87 and 180 for 32- and 64-bit
|
||||
* systems, respectively (approximately 348 and 1440 bytes, respectively).
|
||||
*/
|
||||
|
||||
// Size the path arrays such that they are always large enough, even if a
|
||||
// tree consumes all of memory. Since each node must contain a minimum of
|
||||
// two pointers, there can never be more nodes than:
|
||||
//
|
||||
// 1 << ((sizeof(void*)<<3) - (log2(sizeof(void*))+1))
|
||||
//
|
||||
// Since the depth of a tree is limited to 3*lg(#nodes), the maximum depth
|
||||
// is:
|
||||
//
|
||||
// (3 * ((sizeof(void*)<<3) - (log2(sizeof(void*))+1)))
|
||||
//
|
||||
// This works out to a maximum depth of 87 and 180 for 32- and 64-bit
|
||||
// systems, respectively (approximately 348 and 1440 bytes, respectively).
|
||||
public:
|
||||
class Iterator
|
||||
{
|
||||
@ -723,7 +719,7 @@ public:
|
||||
explicit Iterator(RedBlackTree<T, Trait>* aTree)
|
||||
: mDepth(0)
|
||||
{
|
||||
/* Initialize the path to contain the left spine. */
|
||||
// Initialize the path to contain the left spine.
|
||||
if (aTree->mRoot) {
|
||||
TreeNode* node;
|
||||
mPath[mDepth++] = aTree->mRoot;
|
||||
@ -773,14 +769,14 @@ public:
|
||||
{
|
||||
TreeNode* node;
|
||||
if ((node = mPath[mDepth - 1]->Right())) {
|
||||
/* The successor is the left-most node in the right subtree. */
|
||||
// The successor is the left-most node in the right subtree.
|
||||
mPath[mDepth++] = node;
|
||||
while ((node = mPath[mDepth - 1]->Left())) {
|
||||
mPath[mDepth++] = node;
|
||||
}
|
||||
} else {
|
||||
/* The successor is above the current node. Unwind until a
|
||||
* left-leaning edge is removed from the path, of the path is empty. */
|
||||
// The successor is above the current node. Unwind until a
|
||||
// left-leaning edge is removed from the path, of the path is empty.
|
||||
for (mDepth--; mDepth > 0; mDepth--) {
|
||||
if (mPath[mDepth - 1]->Left() == mPath[mDepth]) {
|
||||
break;
|
||||
@ -794,4 +790,4 @@ public:
|
||||
Iterator iter() { return Iterator(this); }
|
||||
};
|
||||
|
||||
#endif /* RB_H_ */
|
||||
#endif // RB_H_
|
||||
|
@ -7,58 +7,56 @@
|
||||
#ifndef replace_malloc_h
|
||||
#define replace_malloc_h
|
||||
|
||||
/*
|
||||
* The replace_malloc facility allows an external library to replace or
|
||||
* supplement the jemalloc implementation.
|
||||
*
|
||||
* The external library may be hooked by setting one of the following
|
||||
* environment variables to the library path:
|
||||
* - LD_PRELOAD on Linux,
|
||||
* - DYLD_INSERT_LIBRARIES on OSX,
|
||||
* - MOZ_REPLACE_MALLOC_LIB on Windows and Android.
|
||||
*
|
||||
* An initialization function is called before any malloc replacement
|
||||
* function, and has the following declaration:
|
||||
*
|
||||
* void replace_init(const malloc_table_t *)
|
||||
*
|
||||
* The const malloc_table_t pointer given to that function is a table
|
||||
* containing pointers to the original jemalloc implementation, so that
|
||||
* replacement functions can call them back if they need to. The pointer
|
||||
* itself can safely be kept around (no need to copy the table itself).
|
||||
*
|
||||
* The functions to be implemented in the external library are of the form:
|
||||
*
|
||||
* void *replace_malloc(size_t size)
|
||||
* {
|
||||
* // Fiddle with the size if necessary.
|
||||
* // orig->malloc doesn't have to be called if the external library
|
||||
* // provides its own allocator, but in this case it will have to
|
||||
* // implement all functions.
|
||||
* void *ptr = orig->malloc(size);
|
||||
* // Do whatever you want with the ptr.
|
||||
* return ptr;
|
||||
* }
|
||||
*
|
||||
* where "orig" is the pointer obtained from replace_init.
|
||||
*
|
||||
* See malloc_decls.h for a list of functions that can be replaced this
|
||||
* way. The implementations are all in the form:
|
||||
* return_type replace_name(arguments [,...])
|
||||
*
|
||||
* They don't all need to be provided.
|
||||
*
|
||||
* Building a replace-malloc library is like rocket science. It can end up
|
||||
* with things blowing up, especially when trying to use complex types, and
|
||||
* even more especially when these types come from XPCOM or other parts of the
|
||||
* Mozilla codebase.
|
||||
* It is recommended to add the following to a replace-malloc implementation's
|
||||
* moz.build:
|
||||
* DISABLE_STL_WRAPPING = True # Avoid STL wrapping
|
||||
*
|
||||
* If your replace-malloc implementation lives under memory/replace, these
|
||||
* are taken care of by memory/replace/defs.mk.
|
||||
*/
|
||||
// The replace_malloc facility allows an external library to replace or
|
||||
// supplement the jemalloc implementation.
|
||||
//
|
||||
// The external library may be hooked by setting one of the following
|
||||
// environment variables to the library path:
|
||||
// - LD_PRELOAD on Linux,
|
||||
// - DYLD_INSERT_LIBRARIES on OSX,
|
||||
// - MOZ_REPLACE_MALLOC_LIB on Windows and Android.
|
||||
//
|
||||
// An initialization function is called before any malloc replacement
|
||||
// function, and has the following declaration:
|
||||
//
|
||||
// void replace_init(const malloc_table_t *)
|
||||
//
|
||||
// The const malloc_table_t pointer given to that function is a table
|
||||
// containing pointers to the original jemalloc implementation, so that
|
||||
// replacement functions can call them back if they need to. The pointer
|
||||
// itself can safely be kept around (no need to copy the table itself).
|
||||
//
|
||||
// The functions to be implemented in the external library are of the form:
|
||||
//
|
||||
// void *replace_malloc(size_t size)
|
||||
// {
|
||||
// // Fiddle with the size if necessary.
|
||||
// // orig->malloc doesn't have to be called if the external library
|
||||
// // provides its own allocator, but in this case it will have to
|
||||
// // implement all functions.
|
||||
// void *ptr = orig->malloc(size);
|
||||
// // Do whatever you want with the ptr.
|
||||
// return ptr;
|
||||
// }
|
||||
//
|
||||
// where "orig" is the pointer obtained from replace_init.
|
||||
//
|
||||
// See malloc_decls.h for a list of functions that can be replaced this
|
||||
// way. The implementations are all in the form:
|
||||
// return_type replace_name(arguments [,...])
|
||||
//
|
||||
// They don't all need to be provided.
|
||||
//
|
||||
// Building a replace-malloc library is like rocket science. It can end up
|
||||
// with things blowing up, especially when trying to use complex types, and
|
||||
// even more especially when these types come from XPCOM or other parts of the
|
||||
// Mozilla codebase.
|
||||
// It is recommended to add the following to a replace-malloc implementation's
|
||||
// moz.build:
|
||||
// DISABLE_STL_WRAPPING = True # Avoid STL wrapping
|
||||
//
|
||||
// If your replace-malloc implementation lives under memory/replace, these
|
||||
// are taken care of by memory/replace/defs.mk.
|
||||
|
||||
#ifdef replace_malloc_bridge_h
|
||||
#error Do not include replace_malloc_bridge.h before replace_malloc.h. \
|
||||
@ -69,16 +67,16 @@
|
||||
|
||||
#include "replace_malloc_bridge.h"
|
||||
|
||||
/* Implementing a replace-malloc library is incompatible with using mozalloc. */
|
||||
// Implementing a replace-malloc library is incompatible with using mozalloc.
|
||||
#define MOZ_NO_MOZALLOC 1
|
||||
|
||||
#include "mozilla/Types.h"
|
||||
|
||||
MOZ_BEGIN_EXTERN_C
|
||||
|
||||
/* MOZ_NO_REPLACE_FUNC_DECL and MOZ_REPLACE_WEAK are only defined in
|
||||
* replace_malloc.c. Normally including this header will add function
|
||||
* definitions. */
|
||||
// MOZ_NO_REPLACE_FUNC_DECL and MOZ_REPLACE_WEAK are only defined in
|
||||
// replace_malloc.c. Normally including this header will add function
|
||||
// definitions.
|
||||
#ifndef MOZ_NO_REPLACE_FUNC_DECL
|
||||
|
||||
# ifndef MOZ_REPLACE_WEAK
|
||||
@ -91,8 +89,8 @@ MOZ_BEGIN_EXTERN_C
|
||||
# define MALLOC_FUNCS MALLOC_FUNCS_ALL
|
||||
# include "malloc_decls.h"
|
||||
|
||||
#endif /* MOZ_NO_REPLACE_FUNC_DECL */
|
||||
#endif // MOZ_NO_REPLACE_FUNC_DECL
|
||||
|
||||
MOZ_END_EXTERN_C
|
||||
|
||||
#endif /* replace_malloc_h */
|
||||
#endif // replace_malloc_h
|
||||
|
@ -7,44 +7,42 @@
|
||||
#ifndef replace_malloc_bridge_h
|
||||
#define replace_malloc_bridge_h
|
||||
|
||||
/*
|
||||
* The replace-malloc bridge allows bidirectional method calls between
|
||||
* a program and the replace-malloc library that has been loaded for it.
|
||||
* In Firefox, this is used to allow method calls between code in libxul
|
||||
* and code in the replace-malloc library, without libxul needing to link
|
||||
* against that library or vice-versa.
|
||||
*
|
||||
* Subsystems can add methods for their own need. Replace-malloc libraries
|
||||
* can decide to implement those methods or not.
|
||||
*
|
||||
* Replace-malloc libraries can provide such a bridge by implementing
|
||||
* a ReplaceMallocBridge-derived class, and a replace_get_bridge function
|
||||
* returning an instance of that class. The default methods in
|
||||
* ReplaceMallocBridge are expected to return values that callers would
|
||||
* understand as "the bridge doesn't implement this method", so that a
|
||||
* replace-malloc library doesn't have to implement all methods.
|
||||
*
|
||||
* The ReplaceMallocBridge class contains definitions for methods for
|
||||
* all replace-malloc libraries. Each library picks the methods it wants
|
||||
* to reply to in its ReplaceMallocBridge-derived class instance.
|
||||
* All methods of ReplaceMallocBridge must be virtual. Similarly,
|
||||
* anything passed as an argument to those methods must be plain data, or
|
||||
* an instance of a class with only virtual methods.
|
||||
*
|
||||
* Binary compatibility is expected to be maintained, such that a newer
|
||||
* Firefox can be used with an old replace-malloc library, or an old
|
||||
* Firefox can be used with a newer replace-malloc library. As such, only
|
||||
* new virtual methods should be added to ReplaceMallocBridge, and
|
||||
* each change should have a corresponding bump of the mVersion value.
|
||||
* At the same time, each virtual method should have a corresponding
|
||||
* wrapper calling the virtual method on the instance from
|
||||
* ReplaceMallocBridge::Get(), giving it the version the virtual method
|
||||
* was added.
|
||||
*
|
||||
* Parts that are not relevant to the replace-malloc library end of the
|
||||
* bridge are hidden when REPLACE_MALLOC_IMPL is not defined, which is
|
||||
* the case when including replace_malloc.h.
|
||||
*/
|
||||
// The replace-malloc bridge allows bidirectional method calls between
|
||||
// a program and the replace-malloc library that has been loaded for it.
|
||||
// In Firefox, this is used to allow method calls between code in libxul
|
||||
// and code in the replace-malloc library, without libxul needing to link
|
||||
// against that library or vice-versa.
|
||||
//
|
||||
// Subsystems can add methods for their own need. Replace-malloc libraries
|
||||
// can decide to implement those methods or not.
|
||||
//
|
||||
// Replace-malloc libraries can provide such a bridge by implementing
|
||||
// a ReplaceMallocBridge-derived class, and a replace_get_bridge function
|
||||
// returning an instance of that class. The default methods in
|
||||
// ReplaceMallocBridge are expected to return values that callers would
|
||||
// understand as "the bridge doesn't implement this method", so that a
|
||||
// replace-malloc library doesn't have to implement all methods.
|
||||
//
|
||||
// The ReplaceMallocBridge class contains definitions for methods for
|
||||
// all replace-malloc libraries. Each library picks the methods it wants
|
||||
// to reply to in its ReplaceMallocBridge-derived class instance.
|
||||
// All methods of ReplaceMallocBridge must be virtual. Similarly,
|
||||
// anything passed as an argument to those methods must be plain data, or
|
||||
// an instance of a class with only virtual methods.
|
||||
//
|
||||
// Binary compatibility is expected to be maintained, such that a newer
|
||||
// Firefox can be used with an old replace-malloc library, or an old
|
||||
// Firefox can be used with a newer replace-malloc library. As such, only
|
||||
// new virtual methods should be added to ReplaceMallocBridge, and
|
||||
// each change should have a corresponding bump of the mVersion value.
|
||||
// At the same time, each virtual method should have a corresponding
|
||||
// wrapper calling the virtual method on the instance from
|
||||
// ReplaceMallocBridge::Get(), giving it the version the virtual method
|
||||
// was added.
|
||||
//
|
||||
// Parts that are not relevant to the replace-malloc library end of the
|
||||
// bridge are hidden when REPLACE_MALLOC_IMPL is not defined, which is
|
||||
// the case when including replace_malloc.h.
|
||||
|
||||
struct ReplaceMallocBridge;
|
||||
|
||||
@ -53,13 +51,13 @@ struct ReplaceMallocBridge;
|
||||
MOZ_BEGIN_EXTERN_C
|
||||
|
||||
#ifndef REPLACE_MALLOC_IMPL
|
||||
/* Returns the replace-malloc bridge if there is one to be returned. */
|
||||
// Returns the replace-malloc bridge if there is one to be returned.
|
||||
MFBT_API ReplaceMallocBridge* get_bridge();
|
||||
#endif
|
||||
|
||||
/* Table of malloc functions.
|
||||
* e.g. void* (*malloc)(size_t), etc.
|
||||
*/
|
||||
// Table of malloc functions.
|
||||
// e.g. void* (*malloc)(size_t), etc.
|
||||
|
||||
#define MALLOC_DECL(name, return_type, ...) \
|
||||
typedef return_type(name ## _impl_t)(__VA_ARGS__);
|
||||
|
||||
@ -76,18 +74,17 @@ MOZ_END_EXTERN_C
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
/* Table of malloc hook functions.
|
||||
* Those functions are called with the arguments and results of malloc
|
||||
* functions after they are called.
|
||||
* e.g. void* (*malloc_hook)(void*, size_t), etc.
|
||||
* They can either return the result they're given, or alter it before
|
||||
* returning it.
|
||||
* The hooks corresponding to functions, like free(void*), that return no
|
||||
* value, don't take an extra argument.
|
||||
* The table must at least contain a pointer for malloc_hook and free_hook
|
||||
* functions. They will be used as fallback if no pointer is given for
|
||||
* other allocation functions, like calloc_hook.
|
||||
*/
|
||||
// Table of malloc hook functions.
|
||||
// Those functions are called with the arguments and results of malloc
|
||||
// functions after they are called.
|
||||
// e.g. void* (*malloc_hook)(void*, size_t), etc.
|
||||
// They can either return the result they're given, or alter it before
|
||||
// returning it.
|
||||
// The hooks corresponding to functions, like free(void*), that return no
|
||||
// value, don't take an extra argument.
|
||||
// The table must at least contain a pointer for malloc_hook and free_hook
|
||||
// functions. They will be used as fallback if no pointer is given for
|
||||
// other allocation functions, like calloc_hook.
|
||||
namespace mozilla {
|
||||
namespace detail {
|
||||
template <typename R, typename... Args>
|
||||
@ -110,8 +107,8 @@ struct AllocHookType<void, Args...>
|
||||
|
||||
typedef struct {
|
||||
#include "malloc_decls.h"
|
||||
/* Like free_hook, but called before realloc_hook. free_hook is called
|
||||
* instead of not given. */
|
||||
// Like free_hook, but called before realloc_hook. free_hook is called
|
||||
// instead of not given.
|
||||
void (*realloc_hook_before)(void* aPtr);
|
||||
} malloc_hook_table_t;
|
||||
|
||||
@ -120,8 +117,8 @@ namespace dmd {
|
||||
struct DMDFuncs;
|
||||
} // namespace dmd
|
||||
|
||||
/* Callbacks to register debug file handles for Poison IO interpose.
|
||||
* See Mozilla(|Un)RegisterDebugHandle in xpcom/build/PoisonIOInterposer.h */
|
||||
// Callbacks to register debug file handles for Poison IO interpose.
|
||||
// See Mozilla(|Un)RegisterDebugHandle in xpcom/build/PoisonIOInterposer.h
|
||||
struct DebugFdRegistry
|
||||
{
|
||||
virtual void RegisterHandle(intptr_t aFd);
|
||||
@ -135,35 +132,35 @@ struct ReplaceMallocBridge
|
||||
{
|
||||
ReplaceMallocBridge() : mVersion(3) {}
|
||||
|
||||
/* This method was added in version 1 of the bridge. */
|
||||
// This method was added in version 1 of the bridge.
|
||||
virtual mozilla::dmd::DMDFuncs* GetDMDFuncs() { return nullptr; }
|
||||
|
||||
/* Send a DebugFdRegistry instance to the replace-malloc library so that
|
||||
* it can register/unregister file descriptors whenever needed. The
|
||||
* instance is valid until the process dies.
|
||||
* This method was added in version 2 of the bridge. */
|
||||
// Send a DebugFdRegistry instance to the replace-malloc library so that
|
||||
// it can register/unregister file descriptors whenever needed. The
|
||||
// instance is valid until the process dies.
|
||||
// This method was added in version 2 of the bridge.
|
||||
virtual void InitDebugFd(mozilla::DebugFdRegistry&) {}
|
||||
|
||||
/* Register a list of malloc functions and hook functions to the
|
||||
* replace-malloc library so that it can choose to dispatch to them
|
||||
* when needed. The details of what is dispatched when is left to the
|
||||
* replace-malloc library.
|
||||
* Passing a nullptr for either table will unregister a previously
|
||||
* registered table under the same name.
|
||||
* Returns nullptr if registration failed.
|
||||
* If registration succeeded, a table of "pure" malloc functions is
|
||||
* returned. Those "pure" malloc functions won't call hooks.
|
||||
* /!\ Do not rely on registration/unregistration to be instantaneous.
|
||||
* Functions from a previously registered table may still be called for
|
||||
* a brief time after RegisterHook returns.
|
||||
* This method was added in version 3 of the bridge. */
|
||||
// Register a list of malloc functions and hook functions to the
|
||||
// replace-malloc library so that it can choose to dispatch to them
|
||||
// when needed. The details of what is dispatched when is left to the
|
||||
// replace-malloc library.
|
||||
// Passing a nullptr for either table will unregister a previously
|
||||
// registered table under the same name.
|
||||
// Returns nullptr if registration failed.
|
||||
// If registration succeeded, a table of "pure" malloc functions is
|
||||
// returned. Those "pure" malloc functions won't call hooks.
|
||||
// /!\ Do not rely on registration/unregistration to be instantaneous.
|
||||
// Functions from a previously registered table may still be called for
|
||||
// a brief time after RegisterHook returns.
|
||||
// This method was added in version 3 of the bridge.
|
||||
virtual const malloc_table_t*
|
||||
RegisterHook(const char* aName, const malloc_table_t* aTable,
|
||||
const malloc_hook_table_t* aHookTable) { return nullptr; }
|
||||
|
||||
#ifndef REPLACE_MALLOC_IMPL
|
||||
/* Returns the replace-malloc bridge if its version is at least the
|
||||
* requested one. */
|
||||
// Returns the replace-malloc bridge if its version is at least the
|
||||
// requested one.
|
||||
static ReplaceMallocBridge* Get(int aMinimumVersion) {
|
||||
static ReplaceMallocBridge* sSingleton = get_bridge();
|
||||
return (sSingleton && sSingleton->mVersion >= aMinimumVersion)
|
||||
@ -176,16 +173,16 @@ protected:
|
||||
};
|
||||
|
||||
#ifndef REPLACE_MALLOC_IMPL
|
||||
/* Class containing wrappers for calls to ReplaceMallocBridge methods.
|
||||
* Those wrappers need to be static methods in a class because compilers
|
||||
* complain about unused static global functions, and linkers complain
|
||||
* about multiple definitions of non-static global functions.
|
||||
* Using a separate class from ReplaceMallocBridge allows the function
|
||||
* names to be identical. */
|
||||
// Class containing wrappers for calls to ReplaceMallocBridge methods.
|
||||
// Those wrappers need to be static methods in a class because compilers
|
||||
// complain about unused static global functions, and linkers complain
|
||||
// about multiple definitions of non-static global functions.
|
||||
// Using a separate class from ReplaceMallocBridge allows the function
|
||||
// names to be identical.
|
||||
struct ReplaceMalloc
|
||||
{
|
||||
/* Don't call this method from performance critical code. Use
|
||||
* mozilla::dmd::DMDFuncs::Get() instead, it has less overhead. */
|
||||
// Don't call this method from performance critical code. Use
|
||||
// mozilla::dmd::DMDFuncs::Get() instead, it has less overhead.
|
||||
static mozilla::dmd::DMDFuncs* GetDMDFuncs()
|
||||
{
|
||||
auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 1);
|
||||
@ -211,6 +208,6 @@ struct ReplaceMalloc
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* __cplusplus */
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif /* replace_malloc_bridge_h */
|
||||
#endif // replace_malloc_bridge_h
|
||||
|
@ -10,10 +10,9 @@
|
||||
#include <mach/mach_types.h>
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
/*
|
||||
* Malloc implementation functions are MOZ_MEMORY_API, and jemalloc
|
||||
* specific functions MOZ_JEMALLOC_API; see mozmemory_wrap.h
|
||||
*/
|
||||
// Malloc implementation functions are MOZ_MEMORY_API, and jemalloc
|
||||
// specific functions MOZ_JEMALLOC_API; see mozmemory_wrap.h
|
||||
|
||||
#define MALLOC_DECL(name, return_type, ...) \
|
||||
MOZ_MEMORY_API return_type name ## _impl(__VA_ARGS__);
|
||||
#define MALLOC_FUNCS MALLOC_FUNCS_MALLOC
|
||||
@ -24,11 +23,10 @@
|
||||
#define MALLOC_FUNCS MALLOC_FUNCS_JEMALLOC
|
||||
#include "malloc_decls.h"
|
||||
|
||||
/*
|
||||
* Definitions of the following structs in malloc/malloc.h might be too old
|
||||
* for the built binary to run on newer versions of OSX. So use the newest
|
||||
* possible version of those structs.
|
||||
*/
|
||||
// Definitions of the following structs in malloc/malloc.h might be too old
|
||||
// for the built binary to run on newer versions of OSX. So use the newest
|
||||
// possible version of those structs.
|
||||
|
||||
typedef struct _malloc_zone_t {
|
||||
void *reserved1;
|
||||
void *reserved2;
|
||||
@ -102,13 +100,11 @@ extern void malloc_zone_free(malloc_zone_t* zone, void* ptr);
|
||||
|
||||
extern void* malloc_zone_realloc(malloc_zone_t* zone, void* ptr, size_t size);
|
||||
|
||||
/*
|
||||
* The following is a OSX zone allocator implementation.
|
||||
* /!\ WARNING. It assumes the underlying malloc implementation's
|
||||
* malloc_usable_size returns 0 when the given pointer is not owned by
|
||||
* the allocator. Sadly, OSX does call zone_size with pointers not
|
||||
* owned by the allocator.
|
||||
*/
|
||||
// The following is a OSX zone allocator implementation.
|
||||
// /!\ WARNING. It assumes the underlying malloc implementation's
|
||||
// malloc_usable_size returns 0 when the given pointer is not owned by
|
||||
// the allocator. Sadly, OSX does call zone_size with pointers not
|
||||
// owned by the allocator.
|
||||
|
||||
static size_t
|
||||
zone_size(malloc_zone_t *zone, const void *ptr)
|
||||
@ -206,7 +202,7 @@ zone_valloc(malloc_zone_t *zone, size_t size)
|
||||
static void
|
||||
zone_destroy(malloc_zone_t *zone)
|
||||
{
|
||||
/* This function should never be called. */
|
||||
// This function should never be called.
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
||||
@ -279,23 +275,23 @@ extern void _malloc_postfork_child(void);
|
||||
static void
|
||||
zone_force_lock(malloc_zone_t *zone)
|
||||
{
|
||||
/* /!\ This calls into mozjemalloc. It works because we're linked in the
|
||||
* same library. */
|
||||
// /!\ This calls into mozjemalloc. It works because we're linked in the
|
||||
// same library.
|
||||
_malloc_prefork();
|
||||
}
|
||||
|
||||
static void
|
||||
zone_force_unlock(malloc_zone_t *zone)
|
||||
{
|
||||
/* /!\ This calls into mozjemalloc. It works because we're linked in the
|
||||
* same library. */
|
||||
// /!\ This calls into mozjemalloc. It works because we're linked in the
|
||||
// same library.
|
||||
_malloc_postfork_child();
|
||||
}
|
||||
|
||||
static void
|
||||
zone_statistics(malloc_zone_t *zone, malloc_statistics_t *stats)
|
||||
{
|
||||
/* We make no effort to actually fill the values */
|
||||
// We make no effort to actually fill the values
|
||||
stats->blocks_in_use = 0;
|
||||
stats->size_in_use = 0;
|
||||
stats->max_size_in_use = 0;
|
||||
@ -305,15 +301,15 @@ zone_statistics(malloc_zone_t *zone, malloc_statistics_t *stats)
|
||||
static boolean_t
|
||||
zone_locked(malloc_zone_t *zone)
|
||||
{
|
||||
/* Pretend no lock is being held */
|
||||
// Pretend no lock is being held
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
zone_reinit_lock(malloc_zone_t *zone)
|
||||
{
|
||||
/* As of OSX 10.12, this function is only used when force_unlock would
|
||||
* be used if the zone version were < 9. So just use force_unlock. */
|
||||
// As of OSX 10.12, this function is only used when force_unlock would
|
||||
// be used if the zone version were < 9. So just use force_unlock.
|
||||
zone_force_unlock(zone);
|
||||
}
|
||||
|
||||
@ -325,19 +321,17 @@ static malloc_zone_t *get_default_zone()
|
||||
malloc_zone_t **zones = NULL;
|
||||
unsigned int num_zones = 0;
|
||||
|
||||
/*
|
||||
* On OSX 10.12, malloc_default_zone returns a special zone that is not
|
||||
* present in the list of registered zones. That zone uses a "lite zone"
|
||||
* if one is present (apparently enabled when malloc stack logging is
|
||||
* enabled), or the first registered zone otherwise. In practice this
|
||||
* means unless malloc stack logging is enabled, the first registered
|
||||
* zone is the default.
|
||||
* So get the list of zones to get the first one, instead of relying on
|
||||
* malloc_default_zone.
|
||||
*/
|
||||
// On OSX 10.12, malloc_default_zone returns a special zone that is not
|
||||
// present in the list of registered zones. That zone uses a "lite zone"
|
||||
// if one is present (apparently enabled when malloc stack logging is
|
||||
// enabled), or the first registered zone otherwise. In practice this
|
||||
// means unless malloc stack logging is enabled, the first registered
|
||||
// zone is the default.
|
||||
// So get the list of zones to get the first one, instead of relying on
|
||||
// malloc_default_zone.
|
||||
if (KERN_SUCCESS != malloc_get_all_zones(0, NULL, (vm_address_t**) &zones,
|
||||
&num_zones)) {
|
||||
/* Reset the value in case the failure happened after it was set. */
|
||||
// Reset the value in case the failure happened after it was set.
|
||||
num_zones = 0;
|
||||
}
|
||||
if (num_zones) {
|
||||
@ -391,42 +385,37 @@ register_zone(void)
|
||||
#endif
|
||||
zone_introspect.reinit_lock = zone_reinit_lock;
|
||||
|
||||
/*
|
||||
* The default purgeable zone is created lazily by OSX's libc. It uses
|
||||
* the default zone when it is created for "small" allocations
|
||||
* (< 15 KiB), but assumes the default zone is a scalable_zone. This
|
||||
* obviously fails when the default zone is the jemalloc zone, so
|
||||
* malloc_default_purgeable_zone is called beforehand so that the
|
||||
* default purgeable zone is created when the default zone is still
|
||||
* a scalable_zone.
|
||||
*/
|
||||
// The default purgeable zone is created lazily by OSX's libc. It uses
|
||||
// the default zone when it is created for "small" allocations
|
||||
// (< 15 KiB), but assumes the default zone is a scalable_zone. This
|
||||
// obviously fails when the default zone is the jemalloc zone, so
|
||||
// malloc_default_purgeable_zone is called beforehand so that the
|
||||
// default purgeable zone is created when the default zone is still
|
||||
// a scalable_zone.
|
||||
malloc_zone_t *purgeable_zone = malloc_default_purgeable_zone();
|
||||
|
||||
/* Register the custom zone. At this point it won't be the default. */
|
||||
// Register the custom zone. At this point it won't be the default.
|
||||
malloc_zone_register(&zone);
|
||||
|
||||
do {
|
||||
/*
|
||||
* Unregister and reregister the default zone. On OSX >= 10.6,
|
||||
* unregistering takes the last registered zone and places it at the
|
||||
* location of the specified zone. Unregistering the default zone thus
|
||||
* makes the last registered one the default. On OSX < 10.6,
|
||||
* unregistering shifts all registered zones. The first registered zone
|
||||
* then becomes the default.
|
||||
*/
|
||||
// Unregister and reregister the default zone. On OSX >= 10.6,
|
||||
// unregistering takes the last registered zone and places it at the
|
||||
// location of the specified zone. Unregistering the default zone thus
|
||||
// makes the last registered one the default. On OSX < 10.6,
|
||||
// unregistering shifts all registered zones. The first registered zone
|
||||
// then becomes the default.
|
||||
malloc_zone_unregister(default_zone);
|
||||
malloc_zone_register(default_zone);
|
||||
/*
|
||||
* On OSX 10.6, having the default purgeable zone appear before the default
|
||||
* zone makes some things crash because it thinks it owns the default
|
||||
* zone allocated pointers. We thus unregister/re-register it in order to
|
||||
* ensure it's always after the default zone. On OSX < 10.6, as
|
||||
* unregistering shifts registered zones, this simply removes the purgeable
|
||||
* zone from the list and adds it back at the end, after the default zone.
|
||||
* On OSX >= 10.6, unregistering replaces the purgeable zone with the last
|
||||
* registered zone above, i.e the default zone. Registering it again then
|
||||
* puts it at the end, obviously after the default zone.
|
||||
*/
|
||||
|
||||
// On OSX 10.6, having the default purgeable zone appear before the default
|
||||
// zone makes some things crash because it thinks it owns the default
|
||||
// zone allocated pointers. We thus unregister/re-register it in order to
|
||||
// ensure it's always after the default zone. On OSX < 10.6, as
|
||||
// unregistering shifts registered zones, this simply removes the purgeable
|
||||
// zone from the list and adds it back at the end, after the default zone.
|
||||
// On OSX >= 10.6, unregistering replaces the purgeable zone with the last
|
||||
// registered zone above, i.e the default zone. Registering it again then
|
||||
// puts it at the end, obviously after the default zone.
|
||||
malloc_zone_unregister(purgeable_zone);
|
||||
malloc_zone_register(purgeable_zone);
|
||||
default_zone = get_default_zone();
|
||||
|
Loading…
Reference in New Issue
Block a user