Bug 1189072 - Make DefaultTracer for struct types call T::trace; r=fitzgen
authorTerrence Cole <terrence@mozilla.com>
Wed, 29 Jul 2015 14:59:49 -0700
changeset 287606 d1288e84b4a039332a52ba194877100b0b6ec598
parent 287605 d6dea3334b6c311107b2fe1e482ca2ad7e133a24
child 287607 abc018892155463bfee51a1cc3d72454904a0bf0
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfitzgen
bugs1189072
milestone42.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 1189072 - Make DefaultTracer for struct types call T::trace; r=fitzgen
js/public/TraceableHashTable.h
js/public/TraceableVector.h
js/public/TracingAPI.h
js/src/ctypes/CTypes.h
--- a/js/public/TraceableHashTable.h
+++ b/js/public/TraceableHashTable.h
@@ -4,21 +4,20 @@
  * 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/. */
 
 #ifndef gc_HashTable_h
 #define gc_HashTable_h
 
 #include "js/HashTable.h"
 #include "js/RootingAPI.h"
+#include "js/TracingAPI.h"
 
 namespace js {
 
-template <typename> struct DefaultTracer;
-
 // A TraceableHashMap is a HashMap with an additional trace method that knows
 // how to visit all keys and values in the table. HashMaps that contain GC
 // pointers that must be traced to be kept alive will generally want to use
 // this TraceableHashMap specializeation in lieu of HashMap.
 //
 // Most types of GC pointers as keys and values can be traced with no extra
 // infrastructure.  For structs and non-gc-pointer members, ensure that there
 // is a specialization of DefaultTracer<T> with an appropriate trace method
@@ -171,17 +170,11 @@ template <typename A, typename B, typena
 class HandleBase<TraceableHashMap<A,B,C,D,E,F>>
   : public TraceableHashMapOperations<JS::Handle<TraceableHashMap<A,B,C,D,E,F>>, A,B,C,D,E,F>
 {
     using Map = TraceableHashMap<A,B,C,D,E,F>;
     friend class TraceableHashMapOperations<JS::Handle<Map>, A,B,C,D,E,F>;
     const Map& extract() const { return *static_cast<const JS::Handle<Map>*>(this)->address(); }
 };
 
-// The default implementation of DefaultTracer will leave alone POD types.
-template <typename T> struct DefaultTracer {
-    static_assert(mozilla::IsPod<T>::value, "non-pod types must not be ignored");
-    static void trace(JSTracer* trc, T* t, const char* name) {}
-};
-
 } /* namespace js */
 
 #endif /* gc_HashTable_h */
--- a/js/public/TraceableVector.h
+++ b/js/public/TraceableVector.h
@@ -3,23 +3,23 @@
  * 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/. */
 
 #ifndef js_TraceableVector_h
 #define js_TraceableVector_h
 
 #include "mozilla/Vector.h"
+
 #include "js/RootingAPI.h"
+#include "js/TracingAPI.h"
 #include "js/Vector.h"
 
 namespace js {
 
-template <typename> struct DefaultTracer;
-
 // A TraceableVector is a Vector with an additional trace method that knows how
 // to visit all of the items stored in the Vector. For vectors that contain GC
 // things, this is usually more convenient than manually iterating and marking
 // the contents.
 //
 // Most types of GC pointers as keys and values can be traced with no extra
 // infrastructure.  For structs and non-gc-pointer members, ensure that there
 // is a specialization of DefaultTracer<T> with an appropriate trace method
--- a/js/public/TracingAPI.h
+++ b/js/public/TracingAPI.h
@@ -254,16 +254,41 @@ class AutoTracingDetails
 
 JS::CallbackTracer*
 JSTracer::asCallbackTracer()
 {
     MOZ_ASSERT(isCallbackTracer());
     return static_cast<JS::CallbackTracer*>(this);
 }
 
+namespace js {
+
+// Automates static dispatch for tracing for TraceableContainers.
+template <typename, typename=void> struct DefaultTracer;
+
+// The default for POD, non-pointer types is to do nothing.
+template <typename T>
+struct DefaultTracer<T, typename mozilla::EnableIf<!mozilla::IsPointer<T>::value &&
+                                                   mozilla::IsPod<T>::value>::Type> {
+    static void trace(JSTracer* trc, T* t, const char* name) {
+        MOZ_ASSERT(mozilla::IsPod<T>::value);
+        MOZ_ASSERT(!mozilla::IsPointer<T>::value);
+    }
+};
+
+// The default for non-pod (e.g. struct) types is to call the trace method.
+template <typename T>
+struct DefaultTracer<T, typename mozilla::EnableIf<!mozilla::IsPod<T>::value>::Type> {
+    static void trace(JSTracer* trc, T* t, const char* name) {
+        t->trace(trc);
+    }
+};
+
+} // namespace js
+
 // The JS_Call*Tracer family of functions traces the given GC thing reference.
 // This performs the tracing action configured on the given JSTracer:
 // typically calling the JSTracer::callback or marking the thing as live.
 //
 // The argument to JS_Call*Tracer is an in-out param: when the function
 // returns, the garbage collector might have moved the GC thing. In this case,
 // the reference passed to JS_Call*Tracer will be updated to the object's new
 // location. Callers of this method are responsible for updating any state
--- a/js/src/ctypes/CTypes.h
+++ b/js/src/ctypes/CTypes.h
@@ -231,16 +231,20 @@ enum TypeCode {
 
 // Descriptor of one field in a StructType. The name of the field is stored
 // as the key to the hash entry.
 struct FieldInfo
 {
   JS::Heap<JSObject*> mType;    // CType of the field
   size_t              mIndex;   // index of the field in the struct (first is 0)
   size_t              mOffset;  // offset of the field in the struct, in bytes
+
+  void trace(JSTracer* trc) {
+    JS_CallObjectTracer(trc, &mType, "fieldType");
+  }
 };
 
 struct UnbarrieredFieldInfo
 {
   JSObject*           mType;    // CType of the field
   size_t              mIndex;   // index of the field in the struct (first is 0)
   size_t              mOffset;  // offset of the field in the struct, in bytes
 };
@@ -529,18 +533,11 @@ namespace Int64 {
   bool IsInt64(JSObject* obj);
 } // namespace Int64
 
 namespace UInt64 {
   bool IsUInt64(JSObject* obj);
 } // namespace UInt64
 
 } // namespace ctypes
-
-template <> struct DefaultTracer<ctypes::FieldInfo> {
-    static void trace(JSTracer* trc, ctypes::FieldInfo* t, const char* name) {
-        JS_CallObjectTracer(trc, &t->mType, "fieldType");
-    }
-};
-
 } // namespace js
 
 #endif /* ctypes_CTypes_h */