Bug 1125096 - Implement JS_DECLARE_NEW_METHODS and JS_DECLARE_MAKE_METHODS using variadic templates, not a gazillion unreadable lines of copypasta. r=jorendorff
authorJeff Walden <jwalden@mit.edu>
Sat, 24 Jan 2015 20:18:21 -0800
changeset 228534 0db39f732328a2bb42c0bb2367a1d32d5edbd47a
parent 228533 3fe8d7d7f9f7373d0d3a3341d1a46347c06c85c7
child 228535 f37bded46028812a125ee184d1ca9a46bc9c05cb
push id28264
push usercbook@mozilla.com
push dateWed, 11 Feb 2015 13:58:35 +0000
treeherdermozilla-central@38058cb42a0e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs1125096
milestone38.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 1125096 - Implement JS_DECLARE_NEW_METHODS and JS_DECLARE_MAKE_METHODS using variadic templates, not a gazillion unreadable lines of copypasta. r=jorendorff
js/public/Utility.h
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -175,356 +175,50 @@ static inline char* js_strdup(const char
  *   operations on the FreeOp provided to the finalizer:
  *
  *     FreeOp::{free_,delete_}
  *
  *   The advantage of these operations is that the memory is batched and freed
  *   on another thread.
  */
 
-#define JS_NEW_BODY(allocator, t, parms)                                       \
-    void *memory = allocator(sizeof(t));                                       \
-    return memory ? new(memory) t parms : nullptr;
-#define JS_MAKE_BODY(newname, T, parms)                                        \
-    T *ptr = newname<T> parms;                                                 \
-    return mozilla::UniquePtr<T, JS::DeletePolicy<T>>(ptr);
-
 /*
- * Given a class which should provide 'new' methods, add
- * JS_DECLARE_NEW_METHODS (see JSContext for a usage example). This
- * adds news with up to 12 parameters. Add more versions of new below if
- * you need more than 12 parameters.
+ * Given a class which should provide a 'new' method, add
+ * JS_DECLARE_NEW_METHODS (see js::MallocProvider for an example).
  *
  * Note: Do not add a ; at the end of a use of JS_DECLARE_NEW_METHODS,
  * or the build will break.
  */
 #define JS_DECLARE_NEW_METHODS(NEWNAME, ALLOCATOR, QUALIFIERS)\
-    template <class T>\
-    QUALIFIERS T *NEWNAME() MOZ_HEAP_ALLOCATOR {\
-        JS_NEW_BODY(ALLOCATOR, T, ())\
-    }\
-\
-    template <class T, class P1>\
-    QUALIFIERS T *NEWNAME(P1 &&p1) MOZ_HEAP_ALLOCATOR {\
-        JS_NEW_BODY(ALLOCATOR, T,\
-                    (mozilla::Forward<P1>(p1)))\
-    }\
-\
-    template <class T, class P1, class P2>\
-    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2) MOZ_HEAP_ALLOCATOR {\
-        JS_NEW_BODY(ALLOCATOR, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3>\
-    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3) MOZ_HEAP_ALLOCATOR {\
-        JS_NEW_BODY(ALLOCATOR, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4>\
-    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4) MOZ_HEAP_ALLOCATOR {\
-        JS_NEW_BODY(ALLOCATOR, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5>\
-    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5) MOZ_HEAP_ALLOCATOR {\
-        JS_NEW_BODY(ALLOCATOR, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6>\
-    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6) MOZ_HEAP_ALLOCATOR {\
-        JS_NEW_BODY(ALLOCATOR, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7>\
-    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7) MOZ_HEAP_ALLOCATOR {\
-        JS_NEW_BODY(ALLOCATOR, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6),\
-                     mozilla::Forward<P7>(p7)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8>\
-    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8) MOZ_HEAP_ALLOCATOR {\
-        JS_NEW_BODY(ALLOCATOR, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6),\
-                     mozilla::Forward<P7>(p7),\
-                     mozilla::Forward<P8>(p8)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9>\
-    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9) MOZ_HEAP_ALLOCATOR {\
-        JS_NEW_BODY(ALLOCATOR, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6),\
-                     mozilla::Forward<P7>(p7),\
-                     mozilla::Forward<P8>(p8),\
-                     mozilla::Forward<P9>(p9)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10>\
-    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9, P10 &&p10) MOZ_HEAP_ALLOCATOR {\
-        JS_NEW_BODY(ALLOCATOR, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6),\
-                     mozilla::Forward<P7>(p7),\
-                     mozilla::Forward<P8>(p8),\
-                     mozilla::Forward<P9>(p9),\
-                     mozilla::Forward<P10>(p10)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11>\
-    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9, P10 &&p10, P11 &&p11) MOZ_HEAP_ALLOCATOR {\
-        JS_NEW_BODY(ALLOCATOR, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6),\
-                     mozilla::Forward<P7>(p7),\
-                     mozilla::Forward<P8>(p8),\
-                     mozilla::Forward<P9>(p9),\
-                     mozilla::Forward<P10>(p10),\
-                     mozilla::Forward<P11>(p11)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12>\
-    QUALIFIERS T *NEWNAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9, P10 &&p10, P11 &&p11, P12 &&p12) MOZ_HEAP_ALLOCATOR {\
-        JS_NEW_BODY(ALLOCATOR, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6),\
-                     mozilla::Forward<P7>(p7),\
-                     mozilla::Forward<P8>(p8),\
-                     mozilla::Forward<P9>(p9),\
-                     mozilla::Forward<P10>(p10),\
-                     mozilla::Forward<P11>(p11),\
-                     mozilla::Forward<P12>(p12)))\
-    }\
+    template <class T, typename... Args> \
+    QUALIFIERS T * \
+    NEWNAME(Args&&... args) MOZ_HEAP_ALLOCATOR { \
+        void *memory = ALLOCATOR(sizeof(T)); \
+        return memory \
+               ? new(memory) T(mozilla::Forward<Args>(args)...) \
+               : nullptr; \
+    }
 
 /*
  * Given a class which should provide 'make' methods, add
- * JS_DECLARE_MAKE_METHODS (see JSContext for a usage example).  This method
- * is functionally the same as JS_DECLARE_NEW_METHODS: it just declares methods
- * that return mozilla::UniquePtr instances that will singly-manage ownership
- * of the created object.  This adds makes with up to 12 parameters.  Add more
- * versions below if you need more than 12 parameters.
+ * JS_DECLARE_MAKE_METHODS (see js::MallocProvider for an example).  This
+ * method is functionally the same as JS_DECLARE_NEW_METHODS: it just declares
+ * methods that return mozilla::UniquePtr instances that will singly-manage
+ * ownership of the created object.
  *
  * Note: Do not add a ; at the end of a use of JS_DECLARE_MAKE_METHODS,
  * or the build will break.
  */
 #define JS_DECLARE_MAKE_METHODS(MAKENAME, NEWNAME, QUALIFIERS)\
-    template <class T> \
-    QUALIFIERS \
-    mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
-    MAKENAME() MOZ_HEAP_ALLOCATOR {\
-        JS_MAKE_BODY(NEWNAME, T, ())\
-    }\
-\
-    template <class T, class P1> \
-    QUALIFIERS \
-    mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
-    MAKENAME(P1 &&p1) MOZ_HEAP_ALLOCATOR {\
-        JS_MAKE_BODY(NEWNAME, T,\
-                    (mozilla::Forward<P1>(p1)))\
-    }\
-\
-    template <class T, class P1, class P2> \
-    QUALIFIERS \
-mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
-    MAKENAME(P1 &&p1, P2 &&p2) MOZ_HEAP_ALLOCATOR {\
-        JS_MAKE_BODY(NEWNAME, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3> \
-    QUALIFIERS \
-    mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
-    MAKENAME(P1 &&p1, P2 &&p2, P3 &&p3) MOZ_HEAP_ALLOCATOR {\
-        JS_MAKE_BODY(NEWNAME, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4> \
-    QUALIFIERS \
-    mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
-    MAKENAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4) MOZ_HEAP_ALLOCATOR {\
-        JS_MAKE_BODY(NEWNAME, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5> \
-    QUALIFIERS \
-    mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
-    MAKENAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5) MOZ_HEAP_ALLOCATOR {\
-        JS_MAKE_BODY(NEWNAME, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6> \
-    QUALIFIERS \
-    mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
-    MAKENAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6) MOZ_HEAP_ALLOCATOR {\
-        JS_MAKE_BODY(NEWNAME, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7> \
-    QUALIFIERS \
-    mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
-    MAKENAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7) MOZ_HEAP_ALLOCATOR {\
-        JS_MAKE_BODY(NEWNAME, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6),\
-                     mozilla::Forward<P7>(p7)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8> \
-    QUALIFIERS \
-    mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
-    MAKENAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8) MOZ_HEAP_ALLOCATOR {\
-        JS_MAKE_BODY(NEWNAME, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6),\
-                     mozilla::Forward<P7>(p7),\
-                     mozilla::Forward<P8>(p8)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9> \
-    QUALIFIERS \
-    mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
-    MAKENAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9) MOZ_HEAP_ALLOCATOR {\
-        JS_MAKE_BODY(NEWNAME, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6),\
-                     mozilla::Forward<P7>(p7),\
-                     mozilla::Forward<P8>(p8),\
-                     mozilla::Forward<P9>(p9)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10> \
-    QUALIFIERS \
-    mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
-    MAKENAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9, P10 &&p10) MOZ_HEAP_ALLOCATOR {\
-        JS_MAKE_BODY(NEWNAME, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6),\
-                     mozilla::Forward<P7>(p7),\
-                     mozilla::Forward<P8>(p8),\
-                     mozilla::Forward<P9>(p9),\
-                     mozilla::Forward<P10>(p10)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11> \
-    QUALIFIERS \
-    mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
-    MAKENAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9, P10 &&p10, P11 &&p11) MOZ_HEAP_ALLOCATOR {\
-        JS_MAKE_BODY(NEWNAME, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6),\
-                     mozilla::Forward<P7>(p7),\
-                     mozilla::Forward<P8>(p8),\
-                     mozilla::Forward<P9>(p9),\
-                     mozilla::Forward<P10>(p10),\
-                     mozilla::Forward<P11>(p11)))\
-    }\
-\
-    template <class T, class P1, class P2, class P3, class P4, class P5, class P6, class P7, class P8, class P9, class P10, class P11, class P12> \
-    QUALIFIERS \
-    mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
-    MAKENAME(P1 &&p1, P2 &&p2, P3 &&p3, P4 &&p4, P5 &&p5, P6 &&p6, P7 &&p7, P8 &&p8, P9 &&p9, P10 &&p10, P11 &&p11, P12 &&p12) MOZ_HEAP_ALLOCATOR {\
-        JS_MAKE_BODY(NEWNAME, T,\
-                    (mozilla::Forward<P1>(p1),\
-                     mozilla::Forward<P2>(p2),\
-                     mozilla::Forward<P3>(p3),\
-                     mozilla::Forward<P4>(p4),\
-                     mozilla::Forward<P5>(p5),\
-                     mozilla::Forward<P6>(p6),\
-                     mozilla::Forward<P7>(p7),\
-                     mozilla::Forward<P8>(p8),\
-                     mozilla::Forward<P9>(p9),\
-                     mozilla::Forward<P10>(p10),\
-                     mozilla::Forward<P11>(p11),\
-                     mozilla::Forward<P12>(p12)))\
-    }\
+    template <class T, typename... Args> \
+    QUALIFIERS mozilla::UniquePtr<T, JS::DeletePolicy<T>> \
+    MAKENAME(Args&&... args) MOZ_HEAP_ALLOCATOR { \
+        T *ptr = NEWNAME<T>(mozilla::Forward<Args>(args)...); \
+        return mozilla::UniquePtr<T, JS::DeletePolicy<T>>(ptr); \
+    }
 
 JS_DECLARE_NEW_METHODS(js_new, js_malloc, static MOZ_ALWAYS_INLINE)
 
 template <class T>
 static MOZ_ALWAYS_INLINE void
 js_delete(T *p)
 {
     if (p) {