Bug 1227535 - Add ZoneAllocPolicy and use it to attribute module memory usage to the zone r=terrence
☠☠ backed out by 8ea3da3e71db ☠ ☠
authorJon Coppeard <jcoppeard@mozilla.com>
Tue, 24 Nov 2015 17:27:35 +0000
changeset 308110 eb9e244e3834403f113ff2652d3627d5da07dbee
parent 308109 226fe77322b7212c9008302588efc898b3366255
child 308111 8ea3da3e71db034ad73719a14e23be22871aabaf
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersterrence
bugs1227535
milestone45.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 1227535 - Add ZoneAllocPolicy and use it to attribute module memory usage to the zone r=terrence
js/src/builtin/ModuleObject.cpp
js/src/builtin/ModuleObject.h
js/src/gc/Zone.h
js/src/jsscript.h
js/src/vm/MallocProvider.h
js/src/vm/ScopeObject.h
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -214,16 +214,21 @@ ExportEntryObject::create(JSContext* cx,
 
 ///////////////////////////////////////////////////////////////////////////
 // IndirectBindingMap
 
 IndirectBindingMap::Binding::Binding(ModuleEnvironmentObject* environment, Shape* shape)
   : environment(environment), shape(shape)
 {}
 
+IndirectBindingMap::IndirectBindingMap(Zone* zone)
+  : map_(ZoneAllocPolicy(zone))
+{
+}
+
 bool
 IndirectBindingMap::init()
 {
     return map_.init();
 }
 
 void
 IndirectBindingMap::trace(JSTracer* trc)
@@ -578,27 +583,30 @@ ModuleObject::isInstance(HandleValue val
 ModuleObject::create(ExclusiveContext* cx, HandleObject enclosingStaticScope)
 {
     Rooted<ModuleObject*> self(cx, NewBuiltinClassInstance<ModuleObject>(cx, TenuredObject));
     if (!self)
         return nullptr;
 
     self->initReservedSlot(StaticScopeSlot, ObjectOrNullValue(enclosingStaticScope));
 
-    IndirectBindingMap* bindings = cx->new_<IndirectBindingMap>();
+    Zone* zone = cx->zone();
+    IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>(zone);
     if (!bindings || !bindings->init()) {
         ReportOutOfMemory(cx);
         return nullptr;
     }
 
     self->initReservedSlot(ImportBindingsSlot, PrivateValue(bindings));
 
-    FunctionDeclarationVector* funDecls = cx->new_<FunctionDeclarationVector>(cx);
-    if (!funDecls)
+    FunctionDeclarationVector* funDecls = zone->new_<FunctionDeclarationVector>(zone);
+    if (!funDecls) {
+        ReportOutOfMemory(cx);
         return nullptr;
+    }
 
     self->initReservedSlot(FunctionDeclarationsSlot, PrivateValue(funDecls));
     return self;
 }
 
 /* static */ void
 ModuleObject::finalize(js::FreeOp* fop, JSObject* obj)
 {
@@ -821,17 +829,18 @@ ModuleObject::evaluate(JSContext* cx, Ha
 ModuleObject::createNamespace(JSContext* cx, HandleModuleObject self, HandleArrayObject exports)
 {
     MOZ_ASSERT(!self->namespace_());
 
     RootedModuleNamespaceObject ns(cx, ModuleNamespaceObject::create(cx, self));
     if (!ns)
         return nullptr;
 
-    IndirectBindingMap* bindings = cx->new_<IndirectBindingMap>();
+    Zone* zone = cx->zone();
+    IndirectBindingMap* bindings = zone->new_<IndirectBindingMap>(zone);
     if (!bindings || !bindings->init()) {
         ReportOutOfMemory(cx);
         return nullptr;
     }
 
     self->initReservedSlot(NamespaceSlot, ObjectValue(*ns));
     self->initReservedSlot(NamespaceExportsSlot, ObjectValue(*exports));
     self->initReservedSlot(NamespaceBindingsSlot, PrivateValue(bindings));
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -5,16 +5,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef builtin_ModuleObject_h
 #define builtin_ModuleObject_h
 
 #include "jsapi.h"
 #include "jsatom.h"
 
+#include "gc/Zone.h"
+
 #include "js/TraceableVector.h"
 
 #include "vm/NativeObject.h"
 #include "vm/ProxyObject.h"
 
 namespace js {
 
 class ModuleEnvironmentObject;
@@ -79,16 +81,17 @@ class ExportEntryObject : public NativeO
 };
 
 typedef Rooted<ExportEntryObject*> RootedExportEntryObject;
 typedef Handle<ExportEntryObject*> HandleExportEntryObject;
 
 class IndirectBindingMap
 {
   public:
+    IndirectBindingMap(Zone* zone);
     bool init();
 
     void trace(JSTracer* trc);
 
     bool putNew(JSContext* cx, HandleId name,
                 HandleModuleEnvironmentObject environment, HandleId localName);
 
     size_t count() const {
@@ -110,17 +113,17 @@ class IndirectBindingMap
   private:
     struct Binding
     {
         Binding(ModuleEnvironmentObject* environment, Shape* shape);
         RelocatablePtr<ModuleEnvironmentObject*> environment;
         RelocatablePtrShape shape;
     };
 
-    typedef HashMap<jsid, Binding, JsidHasher, SystemAllocPolicy> Map;
+    typedef HashMap<jsid, Binding, JsidHasher, ZoneAllocPolicy> Map;
 
     Map map_;
 };
 
 class ModuleNamespaceObject : public ProxyObject
 {
   public:
     static bool isInstance(HandleValue value);
@@ -184,17 +187,17 @@ struct FunctionDeclaration
 {
     FunctionDeclaration(HandleAtom name, HandleFunction fun);
     void trace(JSTracer* trc);
 
     RelocatablePtrAtom name;
     RelocatablePtrFunction fun;
 };
 
-using FunctionDeclarationVector = TraceableVector<FunctionDeclaration>;
+using FunctionDeclarationVector = TraceableVector<FunctionDeclaration, 0, ZoneAllocPolicy>;
 
 class ModuleObject : public NativeObject
 {
   public:
     enum
     {
         ScriptSlot = 0,
         StaticScopeSlot,
--- a/js/src/gc/Zone.h
+++ b/js/src/gc/Zone.h
@@ -139,17 +139,17 @@ struct Zone : public JS::shadow::Zone,
         if (MOZ_UNLIKELY(isTooMuchMalloc()))
             onTooMuchMalloc();
     }
 
     bool isTooMuchMalloc() const { return gcMallocBytes <= 0; }
     void onTooMuchMalloc();
 
     void* onOutOfMemory(js::AllocFunction allocFunc, size_t nbytes, void* reallocPtr = nullptr) {
-        if (!CurrentThreadCanAccessRuntime(runtime_))
+        if (!js::CurrentThreadCanAccessRuntime(runtime_))
             return nullptr;
         return runtimeFromMainThread()->onOutOfMemory(allocFunc, nbytes, reallocPtr);
     }
     void reportAllocationOverflow() { js::ReportAllocationOverflow(nullptr); }
 
     void beginSweepTypes(js::FreeOp* fop, bool releaseTypes);
 
     bool hasMarkedCompartments();
@@ -571,11 +571,67 @@ class CompartmentsIterT
     }
 
     operator JSCompartment*() const { return get(); }
     JSCompartment* operator->() const { return get(); }
 };
 
 typedef CompartmentsIterT<ZonesIter> CompartmentsIter;
 
+/*
+ * Allocation policy that uses Zone::pod_malloc and friends, so that memory
+ * pressure is accounted for on the zone. This is suitable for memory associated
+ * with GC things allocated in the zone.
+ *
+ * Since it doesn't hold a JSContext (those may not live long enough), it can't
+ * report out-of-memory conditions itself; the caller must check for OOM and
+ * take the appropriate action.
+ *
+ * FIXME bug 647103 - replace these *AllocPolicy names.
+ */
+class ZoneAllocPolicy
+{
+    Zone* const zone;
+
+  public:
+    MOZ_IMPLICIT ZoneAllocPolicy(Zone* zone) : zone(zone) {}
+
+    template <typename T>
+    T* maybe_pod_malloc(size_t numElems) {
+        return zone->maybe_pod_malloc<T>(numElems);
+    }
+
+    template <typename T>
+    T* maybe_pod_calloc(size_t numElems) {
+        return zone->maybe_pod_calloc<T>(numElems);
+    }
+
+    template <typename T>
+    T* maybe_pod_realloc(T* p, size_t oldSize, size_t newSize) {
+        return zone->maybe_pod_realloc<T>(p, oldSize, newSize);
+    }
+
+    template <typename T>
+    T* pod_malloc(size_t numElems) {
+        return zone->pod_malloc<T>(numElems);
+    }
+
+    template <typename T>
+    T* pod_calloc(size_t numElems) {
+        return zone->pod_calloc<T>(numElems);
+    }
+
+    template <typename T>
+    T* pod_realloc(T* p, size_t oldSize, size_t newSize) {
+        return zone->pod_realloc<T>(p, oldSize, newSize);
+    }
+
+    void free_(void* p) { js_free(p); }
+    void reportAllocOverflow() const {}
+
+    bool checkSimulatedOOM() const {
+        return !js::oom::ShouldFailWithOOM();
+    }
+};
+
 } // namespace js
 
 #endif // gc_Zone_h
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -13,17 +13,16 @@
 #include "mozilla/PodOperations.h"
 #include "mozilla/UniquePtr.h"
 
 #include "jsatom.h"
 #include "jslock.h"
 #include "jsopcode.h"
 #include "jstypes.h"
 
-#include "builtin/ModuleObject.h"
 #include "gc/Barrier.h"
 #include "gc/Rooting.h"
 #include "jit/IonCode.h"
 #include "js/UbiNode.h"
 #include "vm/NativeObject.h"
 #include "vm/Shape.h"
 
 namespace JS {
@@ -42,16 +41,17 @@ namespace jit {
 # define ION_PENDING_SCRIPT ((js::jit::IonScript*)0x3)
 
 # define BASELINE_DISABLED_SCRIPT ((js::jit::BaselineScript*)0x1)
 
 class BreakpointSite;
 class BindingIter;
 class Debugger;
 class LazyScript;
+class ModuleObject;
 class NestedScopeObject;
 class RegExpObject;
 struct SourceCompressionTask;
 class Shape;
 
 namespace frontend {
     struct BytecodeEmitter;
     class UpvarCookie;
--- a/js/src/vm/MallocProvider.h
+++ b/js/src/vm/MallocProvider.h
@@ -16,19 +16,21 @@
  *
  *   - 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.
+ *         JSContext when allocations fail.
  *
- *       - RuntimeAllocPolicy: forwards to the JSRuntime MallocProvider.
+ *       - RuntimeAllocPolicy: Forwards to the JSRuntime MallocProvider.
+ *
+ *       - ZoneAllocPolicy: Forwards to the Zone MallocProvider.
  *
  *   - 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 only 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.
--- a/js/src/vm/ScopeObject.h
+++ b/js/src/vm/ScopeObject.h
@@ -6,16 +6,17 @@
 
 #ifndef vm_ScopeObject_h
 #define vm_ScopeObject_h
 
 #include "jscntxt.h"
 #include "jsobj.h"
 #include "jsweakmap.h"
 
+#include "builtin/ModuleObject.h"
 #include "gc/Barrier.h"
 #include "vm/ArgumentsObject.h"
 #include "vm/ProxyObject.h"
 
 namespace js {
 
 namespace frontend {
 struct Definition;