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:
Mike Hommey 2017-11-01 17:15:12 +09:00
parent 1de1ed32d0
commit af14262e54
10 changed files with 557 additions and 611 deletions

View File

@ -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

View File

@ -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; }

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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();