michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * Hierarchy of SpiderMonkey system memory allocators: michael@0: * michael@0: * - System {m,c,re}alloc/new/free: Overridden by jemalloc in most michael@0: * environments. Do not use these functions directly. michael@0: * michael@0: * - js_{m,c,re}alloc/new/free: Wraps the system allocators and adds a michael@0: * failure injection framework for use by the fuzzers as well as templated, michael@0: * typesafe variants. See js/public/Utility.h. michael@0: * michael@0: * - AllocPolicy: An interface for the js allocators, for use with templates. michael@0: * These allocators are for system memory whose lifetime is not associated michael@0: * with a GC thing. See js/src/jsalloc.h. michael@0: * michael@0: * - SystemAllocPolicy: No extra functionality over bare allocators. michael@0: * michael@0: * - TempAllocPolicy: Adds automatic error reporting to the provided michael@0: * Context when allocations fail. michael@0: * michael@0: * - MallocProvider. A mixin base class that handles automatically updating michael@0: * the GC's state in response to allocations that are tied to a GC lifetime michael@0: * or are for a particular GC purpose. These allocators must only be used michael@0: * for memory that will be freed when a GC thing is swept. michael@0: * michael@0: * - gc::Zone: Automatically triggers zone GC. michael@0: * - JSRuntime: Automatically triggers full GC. michael@0: * - ThreadsafeContext > ExclusiveContext > JSContext: michael@0: * Dispatches directly to the runtime. michael@0: */ michael@0: michael@0: #ifndef vm_MallocProvider_h michael@0: #define vm_MallocProvider_h michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/Likely.h" michael@0: michael@0: #include "js/Utility.h" michael@0: michael@0: namespace js { michael@0: michael@0: template michael@0: struct MallocProvider michael@0: { michael@0: void *malloc_(size_t bytes) { michael@0: Client *client = static_cast(this); michael@0: client->updateMallocCounter(bytes); michael@0: void *p = js_malloc(bytes); michael@0: return MOZ_LIKELY(!!p) ? p : client->onOutOfMemory(nullptr, bytes); michael@0: } michael@0: michael@0: void *calloc_(size_t bytes) { michael@0: Client *client = static_cast(this); michael@0: client->updateMallocCounter(bytes); michael@0: void *p = js_calloc(bytes); michael@0: return MOZ_LIKELY(!!p) ? p : client->onOutOfMemory(reinterpret_cast(1), bytes); michael@0: } michael@0: michael@0: void *realloc_(void *p, size_t oldBytes, size_t newBytes) { michael@0: Client *client = static_cast(this); michael@0: /* michael@0: * For compatibility we do not account for realloc that decreases michael@0: * previously allocated memory. michael@0: */ michael@0: if (newBytes > oldBytes) michael@0: client->updateMallocCounter(newBytes - oldBytes); michael@0: void *p2 = js_realloc(p, newBytes); michael@0: return MOZ_LIKELY(!!p2) ? p2 : client->onOutOfMemory(p, newBytes); michael@0: } michael@0: michael@0: void *realloc_(void *p, size_t bytes) { michael@0: Client *client = static_cast(this); michael@0: /* michael@0: * For compatibility we do not account for realloc that increases michael@0: * previously allocated memory. michael@0: */ michael@0: if (!p) michael@0: client->updateMallocCounter(bytes); michael@0: void *p2 = js_realloc(p, bytes); michael@0: return MOZ_LIKELY(!!p2) ? p2 : client->onOutOfMemory(p, bytes); michael@0: } michael@0: michael@0: template michael@0: T *pod_malloc() { michael@0: return (T *)malloc_(sizeof(T)); michael@0: } michael@0: michael@0: template michael@0: T *pod_calloc() { michael@0: return (T *)calloc_(sizeof(T)); michael@0: } michael@0: michael@0: template michael@0: T *pod_malloc(size_t numElems) { michael@0: if (numElems & mozilla::tl::MulOverflowMask::value) { michael@0: Client *client = static_cast(this); michael@0: client->reportAllocationOverflow(); michael@0: return nullptr; michael@0: } michael@0: return (T *)malloc_(numElems * sizeof(T)); michael@0: } michael@0: michael@0: template michael@0: T *pod_calloc(size_t numElems, JSCompartment *comp = nullptr, JSContext *cx = nullptr) { michael@0: if (numElems & mozilla::tl::MulOverflowMask::value) { michael@0: Client *client = static_cast(this); michael@0: client->reportAllocationOverflow(); michael@0: return nullptr; michael@0: } michael@0: return (T *)calloc_(numElems * sizeof(T)); michael@0: } michael@0: michael@0: JS_DECLARE_NEW_METHODS(new_, malloc_, MOZ_ALWAYS_INLINE) michael@0: }; michael@0: michael@0: } /* namespace js */ michael@0: michael@0: #endif /* vm_MallocProvider_h */