Bug 963840 - Move MallocProvider out and add a comment about allocation in SpiderMonkey; r=jorendorff
authorTerrence Cole <terrence@mozilla.com>
Fri, 24 Jan 2014 13:22:31 -0800
changeset 166047 08b38c51c5fc094129b019039981e50604a78389
parent 166046 abc4eb237e163e5dc06b9fb5ccef8c4ac85a6fdb
child 166048 fc70e3e4a2418269fb1d65d7159b473b72083f31
push id39115
push usertcole@mozilla.com
push dateThu, 30 Jan 2014 21:12:55 +0000
treeherdermozilla-inbound@08b38c51c5fc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs963840
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 963840 - Move MallocProvider out and add a comment about allocation in SpiderMonkey; r=jorendorff
js/src/jsalloc.h
js/src/vm/MallocProvider.h
js/src/vm/Runtime.h
--- a/js/src/jsalloc.h
+++ b/js/src/jsalloc.h
@@ -1,15 +1,20 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
-/* JS allocation policies. */
+/*
+ * JS allocation policies.
+ *
+ * The allocators here are for system memory with lifetimes which are not
+ * managed by the GC. See the comment at the top of vm/MallocProvider.h.
+ */
 
 #ifndef jsalloc_h
 #define jsalloc_h
 
 #include "js/TypeDecls.h"
 #include "js/Utility.h"
 
 namespace js {
new file mode 100644
--- /dev/null
+++ b/js/src/vm/MallocProvider.h
@@ -0,0 +1,123 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 et sw=4 tw=99:
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * 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/. */
+
+/*
+ * Hierarchy of SpiderMonkey system memory allocators:
+ *
+ *   - System {m,c,re}alloc/new/free: Overridden by jemalloc in most
+ *     environments. Do not use these functions directly.
+ *
+ *   - js_{m,c,re}alloc/new/free: Wraps the system allocators and adds a
+ *     failure injection framework for use by the fuzzers as well as templated,
+ *     typesafe variants. See js/public/Utility.h.
+ *
+ *   - AllocPolicy: An interface for the js allocators, for use with templates.
+ *     These allocators are for system memory whose lifetime is not associated
+ *     with a GC thing. See js/src/jsalloc.h.
+ *
+ *       - SystemAllocPolicy: No extra functionality over bare allocators.
+ *
+ *       - TempAllocPolicy: Adds automatic error reporting to the provided
+ *         Context when allocations fail.
+ *
+ *   - MallocProvider. A mixin base class that handles automatically updating
+ *     the GC's state in response to allocations that are tied to a GC lifetime
+ *     or are for a particular GC purpose. These allocators must ony be used
+ *     for memory that will be freed when a GC thing is swept.
+ *
+ *       - gc::Zone:  Automatically triggers zone GC.
+ *       - JSRuntime: Automatically triggers full GC.
+ *       - ThreadsafeContext > ExclusiveContext > JSContext:
+ *                    Dispatches directly to the runtime.
+ */
+
+#ifndef vm_MallocProvider_h
+#define vm_MallocProvider_h
+
+#include "mozilla/Attributes.h"
+#include "mozilla/Likely.h"
+
+#include "js/Utility.h"
+
+namespace js {
+
+template<class Client>
+struct MallocProvider
+{
+    void *malloc_(size_t bytes) {
+        Client *client = static_cast<Client *>(this);
+        client->updateMallocCounter(bytes);
+        void *p = js_malloc(bytes);
+        return MOZ_LIKELY(!!p) ? p : client->onOutOfMemory(nullptr, bytes);
+    }
+
+    void *calloc_(size_t bytes) {
+        Client *client = static_cast<Client *>(this);
+        client->updateMallocCounter(bytes);
+        void *p = js_calloc(bytes);
+        return MOZ_LIKELY(!!p) ? p : client->onOutOfMemory(reinterpret_cast<void *>(1), bytes);
+    }
+
+    void *realloc_(void *p, size_t oldBytes, size_t newBytes) {
+        Client *client = static_cast<Client *>(this);
+        /*
+         * For compatibility we do not account for realloc that decreases
+         * previously allocated memory.
+         */
+        if (newBytes > oldBytes)
+            client->updateMallocCounter(newBytes - oldBytes);
+        void *p2 = js_realloc(p, newBytes);
+        return MOZ_LIKELY(!!p2) ? p2 : client->onOutOfMemory(p, newBytes);
+    }
+
+    void *realloc_(void *p, size_t bytes) {
+        Client *client = static_cast<Client *>(this);
+        /*
+         * For compatibility we do not account for realloc that increases
+         * previously allocated memory.
+         */
+        if (!p)
+            client->updateMallocCounter(bytes);
+        void *p2 = js_realloc(p, bytes);
+        return MOZ_LIKELY(!!p2) ? p2 : client->onOutOfMemory(p, bytes);
+    }
+
+    template <class T>
+    T *pod_malloc() {
+        return (T *)malloc_(sizeof(T));
+    }
+
+    template <class T>
+    T *pod_calloc() {
+        return (T *)calloc_(sizeof(T));
+    }
+
+    template <class T>
+    T *pod_malloc(size_t numElems) {
+        if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
+            Client *client = static_cast<Client *>(this);
+            client->reportAllocationOverflow();
+            return nullptr;
+        }
+        return (T *)malloc_(numElems * sizeof(T));
+    }
+
+    template <class T>
+    T *pod_calloc(size_t numElems, JSCompartment *comp = nullptr, JSContext *cx = nullptr) {
+        if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
+            Client *client = static_cast<Client *>(this);
+            client->reportAllocationOverflow();
+            return nullptr;
+        }
+        return (T *)calloc_(numElems * sizeof(T));
+    }
+
+    JS_DECLARE_NEW_METHODS(new_, malloc_, MOZ_ALWAYS_INLINE)
+};
+
+} /* namespace js */
+
+#endif /* vm_MallocProvider_h */
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -35,16 +35,17 @@
 #endif
 #ifdef XP_MACOSX
 # include "jit/AsmJSSignalHandlers.h"
 #endif
 #include "js/HashTable.h"
 #include "js/Vector.h"
 #include "vm/CommonPropertyNames.h"
 #include "vm/DateTime.h"
+#include "vm/MallocProvider.h"
 #include "vm/SPSProfiler.h"
 #include "vm/Stack.h"
 #include "vm/ThreadPool.h"
 
 #ifdef _MSC_VER
 #pragma warning(push)
 #pragma warning(disable:4100) /* Silence unreferenced formal parameter warnings */
 #endif
@@ -611,90 +612,16 @@ class PerThreadData : public PerThreadDa
 #ifdef JS_ARM_SIMULATOR
     js::jit::Simulator *simulator() const;
     void setSimulator(js::jit::Simulator *sim);
     js::jit::SimulatorRuntime *simulatorRuntime() const;
     uintptr_t *addressOfSimulatorStackLimit();
 #endif
 };
 
-template<class Client>
-struct MallocProvider
-{
-    void *malloc_(size_t bytes) {
-        Client *client = static_cast<Client *>(this);
-        client->updateMallocCounter(bytes);
-        void *p = js_malloc(bytes);
-        return MOZ_LIKELY(!!p) ? p : client->onOutOfMemory(nullptr, bytes);
-    }
-
-    void *calloc_(size_t bytes) {
-        Client *client = static_cast<Client *>(this);
-        client->updateMallocCounter(bytes);
-        void *p = js_calloc(bytes);
-        return MOZ_LIKELY(!!p) ? p : client->onOutOfMemory(reinterpret_cast<void *>(1), bytes);
-    }
-
-    void *realloc_(void *p, size_t oldBytes, size_t newBytes) {
-        Client *client = static_cast<Client *>(this);
-        /*
-         * For compatibility we do not account for realloc that decreases
-         * previously allocated memory.
-         */
-        if (newBytes > oldBytes)
-            client->updateMallocCounter(newBytes - oldBytes);
-        void *p2 = js_realloc(p, newBytes);
-        return MOZ_LIKELY(!!p2) ? p2 : client->onOutOfMemory(p, newBytes);
-    }
-
-    void *realloc_(void *p, size_t bytes) {
-        Client *client = static_cast<Client *>(this);
-        /*
-         * For compatibility we do not account for realloc that increases
-         * previously allocated memory.
-         */
-        if (!p)
-            client->updateMallocCounter(bytes);
-        void *p2 = js_realloc(p, bytes);
-        return MOZ_LIKELY(!!p2) ? p2 : client->onOutOfMemory(p, bytes);
-    }
-
-    template <class T>
-    T *pod_malloc() {
-        return (T *)malloc_(sizeof(T));
-    }
-
-    template <class T>
-    T *pod_calloc() {
-        return (T *)calloc_(sizeof(T));
-    }
-
-    template <class T>
-    T *pod_malloc(size_t numElems) {
-        if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
-            Client *client = static_cast<Client *>(this);
-            client->reportAllocationOverflow();
-            return nullptr;
-        }
-        return (T *)malloc_(numElems * sizeof(T));
-    }
-
-    template <class T>
-    T *pod_calloc(size_t numElems, JSCompartment *comp = nullptr, JSContext *cx = nullptr) {
-        if (numElems & mozilla::tl::MulOverflowMask<sizeof(T)>::value) {
-            Client *client = static_cast<Client *>(this);
-            client->reportAllocationOverflow();
-            return nullptr;
-        }
-        return (T *)calloc_(numElems * sizeof(T));
-    }
-
-    JS_DECLARE_NEW_METHODS(new_, malloc_, MOZ_ALWAYS_INLINE)
-};
-
 namespace gc {
 class MarkingValidator;
 } // namespace gc
 
 typedef Vector<JS::Zone *, 4, SystemAllocPolicy> ZoneVector;
 
 class AutoLockForExclusiveAccess;
 class AutoLockForCompilation;