Backed out 3 changesets (bug 1221368, bug 1221371) for build failures in B2G JB Emulator. r=backout
authorSebastian Hengst <archaeopteryx@coole-files.de>
Sun, 08 Nov 2015 21:25:22 +0100
changeset 305813 f620224aae8f209bc54bb57f5303e08d1f1055fe
parent 305812 5b50bd85e4a347e9f309a177e1a93082a0916da0
child 305814 b7fb037c6899a58b024117475c8e420f76015986
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)
reviewersbackout
bugs1221368, 1221371
milestone45.0a1
backs outa50c676caf7f12198f892e01ca1fb74fe0753df6
bd99e5060e1e3ecf627a7d5419dda8620c6b5fa6
3a22461c8ce8ee33cd7b37328c774296acc7ee2c
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
Backed out 3 changesets (bug 1221368, bug 1221371) for build failures in B2G JB Emulator. r=backout Backed out changeset a50c676caf7f (bug 1221371) Backed out changeset bd99e5060e1e (bug 1221371) Backed out changeset 3a22461c8ce8 (bug 1221368) gecko/ipc/chromium/src/base/task.h:36:4: error: use of deleted function 'RefPtr<T>::operator T*() const && [with T = nsScreenGonk]' make[6]: *** [nsScreenManagerGonk.o] Error 1
dom/media/gmp/GMPDecryptorChild.cpp
dom/plugins/ipc/PluginInstanceChild.cpp
gfx/layers/ipc/ImageBridgeChild.cpp
ipc/chromium/src/base/task.h
ipc/chromium/src/chrome/common/ipc_message_utils.h
layout/ipc/RenderFrameParent.cpp
mfbt/Assertions.h
mfbt/Tuple.h
mfbt/TypeTraits.h
mfbt/tests/TestTuple.cpp
mfbt/tests/TestTypeTraits.cpp
widget/nsBaseWidget.cpp
--- a/dom/media/gmp/GMPDecryptorChild.cpp
+++ b/dom/media/gmp/GMPDecryptorChild.cpp
@@ -56,17 +56,17 @@ GMPDecryptorChild::CallOnGMPThread(Metho
 {
   if (ON_GMP_THREAD()) {
     // Use forwarding reference when we can.
     CallMethod(aMethod, Forward<ParamType>(aParams)...);
   } else {
     // Use const reference when we have to.
     auto m = &GMPDecryptorChild::CallMethod<
         decltype(aMethod), typename AddConstReference<ParamType>::Type...>;
-    auto t = NewRunnableMethod(this, m, aMethod, Forward<ParamType>(aParams)...);
+    auto t = NewRunnableMethod(this, m, aMethod, aParams...);
     mPlugin->GMPMessageLoop()->PostTask(FROM_HERE, t);
   }
 }
 
 void
 GMPDecryptorChild::Init(GMPDecryptor* aSession)
 {
   MOZ_ASSERT(aSession);
@@ -111,17 +111,17 @@ GMPDecryptorChild::SessionMessage(const 
                                   GMPSessionMessageType aMessageType,
                                   const uint8_t* aMessage,
                                   uint32_t aMessageLength)
 {
   nsTArray<uint8_t> msg;
   msg.AppendElements(aMessage, aMessageLength);
   CALL_ON_GMP_THREAD(SendSessionMessage,
                      nsAutoCString(aSessionId, aSessionIdLength),
-                     aMessageType, Move(msg));
+                     aMessageType, msg);
 }
 
 void
 GMPDecryptorChild::ExpirationChange(const char* aSessionId,
                                     uint32_t aSessionIdLength,
                                     GMPTimestamp aExpiryTime)
 {
   CALL_ON_GMP_THREAD(SendExpirationChange,
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -2559,17 +2559,17 @@ PluginInstanceChild::RecvAsyncSetWindow(
     }
 
     // We shouldn't process this now because it may be received within a nested
     // RPC call, and both Flash and Java don't expect to receive setwindow calls
     // at arbitrary times.
     mCurrentAsyncSetWindowTask =
         NewRunnableMethod<PluginInstanceChild,
                           void (PluginInstanceChild::*)(const gfxSurfaceType&, const NPRemoteWindow&, bool),
-                          const gfxSurfaceType&, const NPRemoteWindow&, bool>
+                          gfxSurfaceType, NPRemoteWindow, bool>
         (this, &PluginInstanceChild::DoAsyncSetWindow,
          aSurfaceType, aWindow, true);
     MessageLoop::current()->PostTask(FROM_HERE, mCurrentAsyncSetWindowTask);
 
     return true;
 }
 
 void
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -453,17 +453,17 @@ void ImageBridgeChild::DispatchReleaseTe
     return;
   }
 
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
     FROM_HERE,
     NewRunnableFunction(&ReleaseTextureClientNow, aClient));
 }
 
-static void UpdateImageClientNow(ImageClient* aClient, RefPtr<ImageContainer>&& aContainer)
+static void UpdateImageClientNow(ImageClient* aClient, ImageContainer* aContainer)
 {
   if (!ImageBridgeChild::IsCreated()) {
     NS_WARNING("Something is holding on to graphics resources after the shutdown"
                "of the graphics subsystem!");
     return;
   }
   MOZ_ASSERT(aClient);
   MOZ_ASSERT(aContainer);
@@ -486,17 +486,20 @@ void ImageBridgeChild::DispatchImageClie
   }
 
   if (InImageBridgeChildThread()) {
     UpdateImageClientNow(aClient, aContainer);
     return;
   }
   sImageBridgeChildSingleton->GetMessageLoop()->PostTask(
     FROM_HERE,
-    NewRunnableFunction(&UpdateImageClientNow, aClient, RefPtr<ImageContainer>(aContainer)));
+    NewRunnableFunction<
+      void (*)(ImageClient*, ImageContainer*),
+      ImageClient*,
+      RefPtr<ImageContainer> >(&UpdateImageClientNow, aClient, aContainer));
 }
 
 static void UpdateAsyncCanvasRendererSync(AsyncCanvasRenderer* aWrapper,
                                           ReentrantMonitor* aBarrier,
                                           bool* const outDone)
 {
   ImageBridgeChild::UpdateAsyncCanvasRendererNow(aWrapper);
 
@@ -535,17 +538,17 @@ void ImageBridgeChild::UpdateAsyncCanvas
 {
   MOZ_ASSERT(aWrapper);
   sImageBridgeChildSingleton->BeginTransaction();
   aWrapper->GetCanvasClient()->Updated();
   sImageBridgeChildSingleton->EndTransaction();
 }
 
 static void FlushAllImagesSync(ImageClient* aClient, ImageContainer* aContainer,
-                               RefPtr<AsyncTransactionWaiter>&& aWaiter)
+                               AsyncTransactionWaiter* aWaiter)
 {
   if (!ImageBridgeChild::IsCreated()) {
     // How sad. If we get into this branch it means that the ImageBridge
     // got destroyed between the time we ImageBridgeChild::FlushAllImage
     // was called on some thread, and the time this function was proxied
     // to the ImageBridge thread. ImageBridge gets destroyed way to late
     // in the shutdown of gecko for this to be happening for a good reason.
     NS_WARNING("Something is holding on to graphics resources after the shutdown"
--- a/ipc/chromium/src/base/task.h
+++ b/ipc/chromium/src/base/task.h
@@ -1,64 +1,19 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
 #ifndef BASE_TASK_H_
 #define BASE_TASK_H_
 
 #include "base/non_thread_safe.h"
 #include "base/revocable_store.h"
 #include "base/tracked.h"
 #include "base/tuple.h"
-#include "mozilla/IndexSequence.h"
-#include "mozilla/Tuple.h"
-
-// Helper functions so that we can call a function a pass it arguments that come
-// from a Tuple.
-
-namespace details {
-
-// Call the given method on the given object. Arguments are passed by move
-// semantics from the given tuple. If the tuple has length N, the sequence must
-// be IndexSequence<0, 1, ..., N-1>.
-template<size_t... Indices, class ObjT, class Method, typename... Args>
-void CallMethod(mozilla::IndexSequence<Indices...>, ObjT* obj, Method method,
-                mozilla::Tuple<Args...>& arg)
-{
-  (obj->*method)(mozilla::Move(mozilla::Get<Indices>(arg))...);
-}
-
-// Same as above, but call a function.
-template<size_t... Indices, typename Function, typename... Args>
-void CallFunction(mozilla::IndexSequence<Indices...>, Function function,
-                  mozilla::Tuple<Args...>& arg)
-{
-  (*function)(mozilla::Move(mozilla::Get<Indices>(arg))...);
-}
-
-} // namespace details
-
-// Call a method on the given object. Arguments are passed by move semantics
-// from the given tuple.
-template<class ObjT, class Method, typename... Args>
-void DispatchTupleToMethod(ObjT* obj, Method method, mozilla::Tuple<Args...>& arg)
-{
-  details::CallMethod(typename mozilla::IndexSequenceFor<Args...>::Type(),
-                      obj, method, arg);
-}
-
-// Same as above, but call a function.
-template<typename Function, typename... Args>
-void DispatchTupleToFunction(Function function, mozilla::Tuple<Args...>& arg)
-{
-  details::CallFunction(typename mozilla::IndexSequenceFor<Args...>::Type(),
-                        function, arg);
-}
 
 // Task ------------------------------------------------------------------------
 //
 // A task is a generic runnable thingy, usually used for running code on a
 // different thread or for scheduling future tasks off of the message loop.
 
 class Task : public tracked_objects::Tracked {
  public:
@@ -150,40 +105,101 @@ class ScopedTaskFactory : public Revocab
 // A ScopedRunnableMethodFactory creates runnable methods for a specified
 // object.  This is particularly useful for generating callbacks for
 // non-reference counted objects when the factory is a member of the object.
 template<class T>
 class ScopedRunnableMethodFactory : public RevocableStore {
  public:
   explicit ScopedRunnableMethodFactory(T* object) : object_(object) { }
 
-  template <class Method, typename... Elements>
-  inline Task* NewRunnableMethod(Method method, Elements&&... elements) {
-    typedef mozilla::Tuple<typename mozilla::Decay<Elements>::Type...> ArgsTuple;
-    typedef RunnableMethod<Method, ArgsTuple> Runnable;
-    typedef typename ScopedTaskFactory<Runnable>::TaskWrapper TaskWrapper;
+  template <class Method>
+  inline Task* NewRunnableMethod(Method method) {
+    typedef typename ScopedTaskFactory<RunnableMethod<
+        Method, Tuple0> >::TaskWrapper TaskWrapper;
+
+    TaskWrapper* task = new TaskWrapper(this);
+    task->Init(object_, method, base::MakeTuple());
+    return task;
+  }
+
+  template <class Method, class A>
+  inline Task* NewRunnableMethod(Method method, const A& a) {
+    typedef typename ScopedTaskFactory<RunnableMethod<
+        Method, Tuple1<A> > >::TaskWrapper TaskWrapper;
+
+    TaskWrapper* task = new TaskWrapper(this);
+    task->Init(object_, method, base::MakeTuple(a));
+    return task;
+  }
+
+  template <class Method, class A, class B>
+  inline Task* NewRunnableMethod(Method method, const A& a, const B& b) {
+    typedef typename ScopedTaskFactory<RunnableMethod<
+        Method, Tuple2<A, B> > >::TaskWrapper TaskWrapper;
 
     TaskWrapper* task = new TaskWrapper(this);
-    task->Init(object_, method, mozilla::MakeTuple(mozilla::Forward<Elements>(elements)...));
+    task->Init(object_, method, base::MakeTuple(a, b));
+    return task;
+  }
+
+  template <class Method, class A, class B, class C>
+  inline Task* NewRunnableMethod(Method method,
+                                 const A& a,
+                                 const B& b,
+                                 const C& c) {
+    typedef typename ScopedTaskFactory<RunnableMethod<
+        Method, Tuple3<A, B, C> > >::TaskWrapper TaskWrapper;
+
+    TaskWrapper* task = new TaskWrapper(this);
+    task->Init(object_, method, base::MakeTuple(a, b, c));
+    return task;
+  }
+
+  template <class Method, class A, class B, class C, class D>
+  inline Task* NewRunnableMethod(Method method,
+                                 const A& a,
+                                 const B& b,
+                                 const C& c,
+                                 const D& d) {
+    typedef typename ScopedTaskFactory<RunnableMethod<
+        Method, Tuple4<A, B, C, D> > >::TaskWrapper TaskWrapper;
+
+    TaskWrapper* task = new TaskWrapper(this);
+    task->Init(object_, method, base::MakeTuple(a, b, c, d));
+    return task;
+  }
+
+  template <class Method, class A, class B, class C, class D, class E>
+  inline Task* NewRunnableMethod(Method method,
+                                 const A& a,
+                                 const B& b,
+                                 const C& c,
+                                 const D& d,
+                                 const E& e) {
+    typedef typename ScopedTaskFactory<RunnableMethod<
+        Method, Tuple5<A, B, C, D, E> > >::TaskWrapper TaskWrapper;
+
+    TaskWrapper* task = new TaskWrapper(this);
+    task->Init(object_, method, base::MakeTuple(a, b, c, d, e));
     return task;
   }
 
  protected:
   template <class Method, class Params>
   class RunnableMethod : public Task {
    public:
     RunnableMethod() { }
 
-    void Init(T* obj, Method meth, Params&& params) {
+    void Init(T* obj, Method meth, const Params& params) {
       obj_ = obj;
       meth_ = meth;
-      params_ = mozilla::Forward<Params>(params);
+      params_ = params;
     }
 
-    virtual void Run() { DispatchTupleToMethod(obj_, meth_, params_); }
+    virtual void Run() { DispatchToMethod(obj_, meth_, params_); }
 
    private:
     T* MOZ_UNSAFE_REF("The validity of this pointer must be enforced by "
                       "external factors.") obj_;
     Method meth_;
     Params params_;
 
     DISALLOW_EVIL_CONSTRUCTORS(RunnableMethod);
@@ -289,80 +305,385 @@ struct RunnableMethodTraits<const T> {
 // PostTask(FROM_HERE, NewRunnableFunction(&function[, a[, b]])
 
 // RunnableMethod and NewRunnableMethod implementation -------------------------
 
 template <class T, class Method, class Params>
 class RunnableMethod : public CancelableTask,
                        public RunnableMethodTraits<T> {
  public:
-  RunnableMethod(T* obj, Method meth, Params&& params)
-      : obj_(obj), meth_(meth), params_(mozilla::Forward<Params>(params)) {
+  RunnableMethod(T* obj, Method meth, const Params& params)
+      : obj_(obj), meth_(meth), params_(params) {
     this->RetainCallee(obj_);
   }
   ~RunnableMethod() {
     ReleaseCallee();
   }
 
   virtual void Run() {
     if (obj_)
-      DispatchTupleToMethod(obj_, meth_, params_);
+      DispatchToMethod(obj_, meth_, params_);
   }
 
   virtual void Cancel() {
     ReleaseCallee();
   }
 
  private:
   void ReleaseCallee() {
     if (obj_) {
       RunnableMethodTraits<T>::ReleaseCallee(obj_);
-      obj_ = nullptr;
+      obj_ = NULL;
     }
   }
 
   // This is owning because of the RetainCallee and ReleaseCallee calls in the
   // constructor and destructor.
   T* MOZ_OWNING_REF obj_;
   Method meth_;
   Params params_;
 };
 
-template <class T, class Method, typename... Args>
-inline CancelableTask* NewRunnableMethod(T* object, Method method, Args&&... args) {
-  typedef mozilla::Tuple<typename mozilla::Decay<Args>::Type...> ArgsTuple;
-  return new RunnableMethod<T, Method, ArgsTuple>(
-      object, method, mozilla::MakeTuple(mozilla::Forward<Args>(args)...));
+template <class T, class Method>
+inline CancelableTask* NewRunnableMethod(T* object, Method method) {
+  return new RunnableMethod<T, Method, Tuple0>(object, method, base::MakeTuple());
+}
+
+template <class T, class Method, class A>
+inline CancelableTask* NewRunnableMethod(T* object, Method method, const A& a) {
+  return new RunnableMethod<T, Method, Tuple1<A> >(object,
+                                                   method,
+                                                   base::MakeTuple(a));
+}
+
+template <class T, class Method, class A, class B>
+inline CancelableTask* NewRunnableMethod(T* object, Method method,
+const A& a, const B& b) {
+  return new RunnableMethod<T, Method, Tuple2<A, B> >(object, method,
+                                                      base::MakeTuple(a, b));
+}
+
+template <class T, class Method, class A, class B, class C>
+inline CancelableTask* NewRunnableMethod(T* object, Method method,
+                                          const A& a, const B& b, const C& c) {
+  return new RunnableMethod<T, Method, Tuple3<A, B, C> >(object, method,
+                                                         base::MakeTuple(a, b, c));
+}
+
+template <class T, class Method, class A, class B, class C, class D>
+inline CancelableTask* NewRunnableMethod(T* object, Method method,
+                                          const A& a, const B& b,
+                                          const C& c, const D& d) {
+  return new RunnableMethod<T, Method, Tuple4<A, B, C, D> >(object, method,
+                                                            base::MakeTuple(a, b,
+                                                                      c, d));
+}
+
+template <class T, class Method, class A, class B, class C, class D, class E>
+inline CancelableTask* NewRunnableMethod(T* object, Method method,
+                                          const A& a, const B& b,
+                                          const C& c, const D& d, const E& e) {
+  return new RunnableMethod<T,
+                            Method,
+                            Tuple5<A, B, C, D, E> >(object,
+                                                    method,
+                                                    base::MakeTuple(a, b, c, d, e));
+}
+
+template <class T, class Method, class A, class B, class C, class D, class E,
+          class F>
+inline CancelableTask* NewRunnableMethod(T* object, Method method,
+                                          const A& a, const B& b,
+                                          const C& c, const D& d, const E& e,
+                                          const F& f) {
+  return new RunnableMethod<T,
+                            Method,
+                            Tuple6<A, B, C, D, E, F> >(object,
+                                                       method,
+                                                       base::MakeTuple(a, b, c, d, e,
+                                                                 f));
+}
+
+template <class T, class Method, class A, class B, class C, class D, class E,
+          class F, class G>
+inline CancelableTask* NewRunnableMethod(T* object, Method method,
+                                         const A& a, const B& b,
+                                         const C& c, const D& d, const E& e,
+                                         const F& f, const G& g) {
+  return new RunnableMethod<T,
+                            Method,
+                            Tuple7<A, B, C, D, E, F, G> >(object,
+                                                          method,
+                                                          base::MakeTuple(a, b, c, d,
+                                                                    e, f, g));
 }
 
 // RunnableFunction and NewRunnableFunction implementation ---------------------
 
 template <class Function, class Params>
 class RunnableFunction : public CancelableTask {
  public:
-  RunnableFunction(Function function, Params&& params)
-      : function_(function), params_(mozilla::Forward<Params>(params)) {
+  RunnableFunction(Function function, const Params& params)
+      : function_(function), params_(params) {
   }
 
   ~RunnableFunction() {
   }
 
   virtual void Run() {
     if (function_)
-      DispatchTupleToFunction(function_, params_);
+      DispatchToFunction(function_, params_);
   }
 
   virtual void Cancel() {
-    function_ = nullptr;
+    function_ = NULL;
   }
 
+ private:
   Function function_;
   Params params_;
 };
 
-template <class Function, typename... Args>
-inline CancelableTask* NewRunnableFunction(Function function, Args&&... args) {
-  typedef mozilla::Tuple<typename mozilla::Decay<Args>::Type...> ArgsTuple;
-  return new RunnableFunction<Function, ArgsTuple>(
-      function, mozilla::MakeTuple(mozilla::Forward<Args>(args)...));
+template <class Function>
+inline CancelableTask* NewRunnableFunction(Function function) {
+  return new RunnableFunction<Function, Tuple0>(function, base::MakeTuple());
+}
+
+template <class Function, class A>
+inline CancelableTask* NewRunnableFunction(Function function, const A& a) {
+  return new RunnableFunction<Function, Tuple1<A> >(function, base::MakeTuple(a));
+}
+
+template <class Function, class A, class B>
+inline CancelableTask* NewRunnableFunction(Function function,
+                                           const A& a, const B& b) {
+  return new RunnableFunction<Function, Tuple2<A, B> >(function,
+                                                       base::MakeTuple(a, b));
+}
+
+template <class Function, class A, class B, class C>
+inline CancelableTask* NewRunnableFunction(Function function,
+                                           const A& a, const B& b,
+                                           const C& c) {
+  return new RunnableFunction<Function, Tuple3<A, B, C> >(function,
+                                                          base::MakeTuple(a, b, c));
+}
+
+template <class Function, class A, class B, class C, class D>
+inline CancelableTask* NewRunnableFunction(Function function,
+                                           const A& a, const B& b,
+                                           const C& c, const D& d) {
+  return new RunnableFunction<Function, Tuple4<A, B, C, D> >(function,
+                                                             base::MakeTuple(a, b,
+                                                                       c, d));
+}
+
+template <class Function, class A, class B, class C, class D, class E>
+inline CancelableTask* NewRunnableFunction(Function function,
+                                           const A& a, const B& b,
+                                           const C& c, const D& d,
+                                           const E& e) {
+  return new RunnableFunction<Function, Tuple5<A, B, C, D, E> >(function,
+                                                                base::MakeTuple(a, b,
+                                                                          c, d,
+                                                                          e));
 }
 
+// Callback --------------------------------------------------------------------
+//
+// A Callback is like a Task but with unbound parameters. It is basically an
+// object-oriented function pointer.
+//
+// Callbacks are designed to work with Tuples.  A set of helper functions and
+// classes is provided to hide the Tuple details from the consumer.  Client
+// code will generally work with the CallbackRunner base class, which merely
+// provides a Run method and is returned by the New* functions. This allows
+// users to not care which type of class implements the callback, only that it
+// has a certain number and type of arguments.
+//
+// The implementation of this is done by CallbackImpl, which inherits
+// CallbackStorage to store the data. This allows the storage of the data
+// (requiring the class type T) to be hidden from users, who will want to call
+// this regardless of the implementor's type T.
+//
+// Note that callbacks currently have no facility for cancelling or abandoning
+// them. We currently handle this at a higher level for cases where this is
+// necessary. The pointer in a callback must remain valid until the callback
+// is made.
+//
+// Like Task, the callback executor is responsible for deleting the callback
+// pointer once the callback has executed.
+//
+// Example client usage:
+//   void Object::DoStuff(int, string);
+//   Callback2<int, string>::Type* callback =
+//       NewCallback(obj, &Object::DoStuff);
+//   callback->Run(5, string("hello"));
+//   delete callback;
+// or, equivalently, using tuples directly:
+//   CallbackRunner<Tuple2<int, string> >* callback =
+//       NewCallback(obj, &Object::DoStuff);
+//   callback->RunWithParams(base::MakeTuple(5, string("hello")));
+
+// Base for all Callbacks that handles storage of the pointers.
+template <class T, typename Method>
+class CallbackStorage {
+ public:
+  CallbackStorage(T* obj, Method meth) : obj_(obj), meth_(meth) {
+  }
+
+ protected:
+  T* MOZ_UNSAFE_REF("The validity of this pointer must be enforced by "
+                    "external factors.") obj_;
+  Method meth_;
+};
+
+// Interface that is exposed to the consumer, that does the actual calling
+// of the method.
+template <typename Params>
+class CallbackRunner {
+ public:
+  typedef Params TupleType;
+
+  virtual ~CallbackRunner() {}
+  virtual void RunWithParams(const Params& params) = 0;
+
+  // Convenience functions so callers don't have to deal with Tuples.
+  inline void Run() {
+    RunWithParams(Tuple0());
+  }
+
+  template <typename Arg1>
+  inline void Run(const Arg1& a) {
+    RunWithParams(Params(a));
+  }
+
+  template <typename Arg1, typename Arg2>
+  inline void Run(const Arg1& a, const Arg2& b) {
+    RunWithParams(Params(a, b));
+  }
+
+  template <typename Arg1, typename Arg2, typename Arg3>
+  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c) {
+    RunWithParams(Params(a, b, c));
+  }
+
+  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c, const Arg4& d) {
+    RunWithParams(Params(a, b, c, d));
+  }
+
+  template <typename Arg1, typename Arg2, typename Arg3,
+            typename Arg4, typename Arg5>
+  inline void Run(const Arg1& a, const Arg2& b, const Arg3& c,
+                  const Arg4& d, const Arg5& e) {
+    RunWithParams(Params(a, b, c, d, e));
+  }
+};
+
+template <class T, typename Method, typename Params>
+class CallbackImpl : public CallbackStorage<T, Method>,
+                     public CallbackRunner<Params> {
+ public:
+  CallbackImpl(T* obj, Method meth) : CallbackStorage<T, Method>(obj, meth) {
+  }
+  virtual void RunWithParams(const Params& params) {
+    // use "this->" to force C++ to look inside our templatized base class; see
+    // Effective C++, 3rd Ed, item 43, p210 for details.
+    DispatchToMethod(this->obj_, this->meth_, params);
+  }
+};
+
+// 0-arg implementation
+struct Callback0 {
+  typedef CallbackRunner<Tuple0> Type;
+};
+
+template <class T>
+typename Callback0::Type* NewCallback(T* object, void (T::*method)()) {
+  return new CallbackImpl<T, void (T::*)(), Tuple0 >(object, method);
+}
+
+// 1-arg implementation
+template <typename Arg1>
+struct Callback1 {
+  typedef CallbackRunner<Tuple1<Arg1> > Type;
+};
+
+template <class T, typename Arg1>
+typename Callback1<Arg1>::Type* NewCallback(T* object,
+                                            void (T::*method)(Arg1)) {
+  return new CallbackImpl<T, void (T::*)(Arg1), Tuple1<Arg1> >(object, method);
+}
+
+// 2-arg implementation
+template <typename Arg1, typename Arg2>
+struct Callback2 {
+  typedef CallbackRunner<Tuple2<Arg1, Arg2> > Type;
+};
+
+template <class T, typename Arg1, typename Arg2>
+typename Callback2<Arg1, Arg2>::Type* NewCallback(
+    T* object,
+    void (T::*method)(Arg1, Arg2)) {
+  return new CallbackImpl<T, void (T::*)(Arg1, Arg2),
+      Tuple2<Arg1, Arg2> >(object, method);
+}
+
+// 3-arg implementation
+template <typename Arg1, typename Arg2, typename Arg3>
+struct Callback3 {
+  typedef CallbackRunner<Tuple3<Arg1, Arg2, Arg3> > Type;
+};
+
+template <class T, typename Arg1, typename Arg2, typename Arg3>
+typename Callback3<Arg1, Arg2, Arg3>::Type* NewCallback(
+    T* object,
+    void (T::*method)(Arg1, Arg2, Arg3)) {
+  return new CallbackImpl<T,  void (T::*)(Arg1, Arg2, Arg3),
+      Tuple3<Arg1, Arg2, Arg3> >(object, method);
+}
+
+// 4-arg implementation
+template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+struct Callback4 {
+  typedef CallbackRunner<Tuple4<Arg1, Arg2, Arg3, Arg4> > Type;
+};
+
+template <class T, typename Arg1, typename Arg2, typename Arg3, typename Arg4>
+typename Callback4<Arg1, Arg2, Arg3, Arg4>::Type* NewCallback(
+    T* object,
+    void (T::*method)(Arg1, Arg2, Arg3, Arg4)) {
+  return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4),
+      Tuple4<Arg1, Arg2, Arg3, Arg4> >(object, method);
+}
+
+// 5-arg implementation
+template <typename Arg1, typename Arg2, typename Arg3,
+          typename Arg4, typename Arg5>
+struct Callback5 {
+  typedef CallbackRunner<Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> > Type;
+};
+
+template <class T, typename Arg1, typename Arg2,
+          typename Arg3, typename Arg4, typename Arg5>
+typename Callback5<Arg1, Arg2, Arg3, Arg4, Arg5>::Type* NewCallback(
+    T* object,
+    void (T::*method)(Arg1, Arg2, Arg3, Arg4, Arg5)) {
+  return new CallbackImpl<T, void (T::*)(Arg1, Arg2, Arg3, Arg4, Arg5),
+      Tuple5<Arg1, Arg2, Arg3, Arg4, Arg5> >(object, method);
+}
+
+// An UnboundMethod is a wrapper for a method where the actual object is
+// provided at Run dispatch time.
+template <class T, class Method, class Params>
+class UnboundMethod {
+ public:
+  UnboundMethod(Method m, Params p) : m_(m), p_(p) {}
+  void Run(T* obj) const {
+    DispatchToMethod(obj, m_, p_);
+  }
+ private:
+  Method m_;
+  Params p_;
+};
+
 #endif  // BASE_TASK_H_
--- a/ipc/chromium/src/chrome/common/ipc_message_utils.h
+++ b/ipc/chromium/src/chrome/common/ipc_message_utils.h
@@ -7,16 +7,17 @@
 
 #include <string>
 #include <vector>
 #include <map>
 
 #include "base/file_path.h"
 #include "base/string_util.h"
 #include "base/string16.h"
+#include "base/tuple.h"
 #include "base/time.h"
 
 #if defined(OS_POSIX)
 #include "chrome/common/file_descriptor_set_posix.h"
 #endif
 #include "chrome/common/ipc_sync_message.h"
 #include "chrome/common/transport_dib.h"
 
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -562,28 +562,28 @@ RenderFrameParent::SetTargetAPZC(uint64_
     }
   }
   if (GetApzcTreeManager()) {
     // need a local var to disambiguate between the SetTargetAPZC overloads.
     void (APZCTreeManager::*setTargetApzcFunc)(uint64_t, const nsTArray<ScrollableLayerGuid>&)
         = &APZCTreeManager::SetTargetAPZC;
     APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
         GetApzcTreeManager(), setTargetApzcFunc,
-        aInputBlockId, nsTArray<ScrollableLayerGuid>(aTargets)));
+        aInputBlockId, aTargets));
   }
 }
 
 void
 RenderFrameParent::SetAllowedTouchBehavior(uint64_t aInputBlockId,
                                            const nsTArray<TouchBehaviorFlags>& aFlags)
 {
   if (GetApzcTreeManager()) {
     APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
         GetApzcTreeManager(), &APZCTreeManager::SetAllowedTouchBehavior,
-        aInputBlockId, nsTArray<TouchBehaviorFlags>(aFlags)));
+        aInputBlockId, aFlags));
   }
 }
 
 void
 RenderFrameParent::UpdateZoomConstraints(uint32_t aPresShellId,
                                          ViewID aViewId,
                                          const Maybe<ZoomConstraints>& aConstraints)
 {
--- a/mfbt/Assertions.h
+++ b/mfbt/Assertions.h
@@ -331,16 +331,28 @@ MOZ_ReportCrash(const char* aStr, const 
  */
 
 #ifdef __cplusplus
 #  include "mozilla/TypeTraits.h"
 namespace mozilla {
 namespace detail {
 
 template<typename T>
+struct IsFunction
+{
+  static const bool value = false;
+};
+
+template<typename R, typename... A>
+struct IsFunction<R(A...)>
+{
+  static const bool value = true;
+};
+
+template<typename T>
 struct AssertionConditionType
 {
   typedef typename RemoveReference<T>::Type ValueT;
   static_assert(!IsArray<ValueT>::value,
                 "Expected boolean assertion condition, got an array or a "
                 "string!");
   static_assert(!IsFunction<ValueT>::value,
                 "Expected boolean assertion condition, got a function! Did "
--- a/mfbt/Tuple.h
+++ b/mfbt/Tuple.h
@@ -412,37 +412,35 @@ auto Get(Tuple<Elements...>&& aTuple)
  * values without specifying the type of the tuple.
  * The type of the tuple is deduced from the types of its elements.
  *
  * Example:
  *
  * auto tuple = MakeTuple(42, 0.5f, 'c');  // has type Tuple<int, float, char>
  */
 template<typename... Elements>
-inline Tuple<typename Decay<Elements>::Type...>
-MakeTuple(Elements&&... aElements)
+Tuple<Elements...> MakeTuple(Elements&&... aElements)
 {
-  return Tuple<typename Decay<Elements>::Type...>(Forward<Elements>(aElements)...);
+  return Tuple<Elements...>(Forward<Elements>(aElements)...);
 }
 
 /**
  * A convenience function for constructing a tuple of references to a
  * sequence of variables. Since assignments to the elements of the tuple
  * "go through" to the referenced variables, this can be used to "unpack"
  * a tuple into individual variables.
  *
  * Example:
  *
  * int i;
  * float f;
  * char c;
  * Tie(i, f, c) = FunctionThatReturnsATuple();
  */
 template<typename... Elements>
-inline Tuple<Elements&...>
-Tie(Elements&... aVariables)
+Tuple<Elements&...> Tie(Elements&... aVariables)
 {
   return Tuple<Elements&...>(aVariables...);
 }
 
 } // namespace mozilla
 
 #endif /* mozilla_Tuple_h */
--- a/mfbt/TypeTraits.h
+++ b/mfbt/TypeTraits.h
@@ -160,50 +160,16 @@ struct IsArrayHelper<T[]> : TrueType {};
  */
 template<typename T>
 struct IsArray : detail::IsArrayHelper<typename RemoveCV<T>::Type>
 {};
 
 namespace detail {
 
 template<typename T>
-struct IsFunPtr;
-
-template<typename>
-struct IsFunPtr
-  : public FalseType
-{};
-
-template<typename Result, typename... ArgTypes>
-struct IsFunPtr<Result(*)(ArgTypes...)>
-  : public TrueType
-{};
-
-}; // namespace detail
-
-/**
- * IsFunction determines whether a type is a function type. Function pointers
- * don't qualify here--only the type of an actual function symbol. We do not
- * correctly handle varags function types because of a bug in MSVC.
- *
- * Given the function:
- *   void f(int) {}
- *
- * mozilla::IsFunction<void(int)> is true;
- * mozilla::IsFunction<void(*)(int)> is false;
- * mozilla::IsFunction<decltype(f)> is true.
- */
-template<typename T>
-struct IsFunction
-  : public detail::IsFunPtr<typename RemoveCV<T>::Type *>
-{};
-
-namespace detail {
-
-template<typename T>
 struct IsPointerHelper : FalseType {};
 
 template<typename T>
 struct IsPointerHelper<T*> : TrueType {};
 
 } // namespace detail
 
 /**
@@ -1092,32 +1058,16 @@ struct RemovePointerHelper<T, Pointee*>
  * mozilla::RemovePointer<void (*)()>::Type is void();
  * mozilla::RemovePointer<bool S::*>::Type is bool S::*.
  */
 template<typename T>
 struct RemovePointer
   : detail::RemovePointerHelper<T, typename RemoveCV<T>::Type>
 {};
 
-/**
- * Converts T& to T*. Otherwise returns T* given T. Note that C++17 wants
- * std::add_pointer to work differently for function types. We don't implement
- * that behavior here.
- *
- * mozilla::AddPointer<int> is int*;
- * mozilla::AddPointer<int*> is int**;
- * mozilla::AddPointer<int&> is int*;
- * mozilla::AddPointer<int* const> is int** const.
- */
-template<typename T>
-struct AddPointer
-{
-  typedef typename RemoveReference<T>::Type* Type;
-};
-
 /* 20.9.7.6 Other transformations [meta.trans.other] */
 
 /**
  * EnableIf is a struct containing a typedef of T if and only if B is true.
  *
  * mozilla::EnableIf<true, int>::Type is int;
  * mozilla::EnableIf<false, int>::Type is a compile-time error.
  *
@@ -1156,56 +1106,11 @@ struct Conditional
 };
 
 template<class A, class B>
 struct Conditional<false, A, B>
 {
   typedef B Type;
 };
 
-namespace detail {
-
-template<typename U,
-         bool IsArray = IsArray<U>::value,
-         bool IsFunction = IsFunction<U>::value>
-struct DecaySelector;
-
-template<typename U>
-struct DecaySelector<U, false, false>
-{
-  typedef typename RemoveCV<U>::Type Type;
-};
-
-template<typename U>
-struct DecaySelector<U, true, false>
-{
-  typedef typename RemoveExtent<U>::Type* Type;
-};
-
-template<typename U>
-struct DecaySelector<U, false, true>
-{
-  typedef typename AddPointer<U>::Type Type;
-};
-
-}; // namespace detail
-
-/**
- * Strips const/volatile off a type and decays it from an lvalue to an
- * rvalue. So function types are converted to function pointers, arrays to
- * pointers, and references are removed.
- *
- * mozilla::Decay<int>::Type is int
- * mozilla::Decay<int&>::Type is int
- * mozilla::Decay<int&&>::Type is int
- * mozilla::Decay<const int&>::Type is int
- * mozilla::Decay<int[2]>::Type is int*
- * mozilla::Decay<int(int)>::Type is int(*)(int)
- */
-template<typename T>
-class Decay
-  : public detail::DecaySelector<typename RemoveReference<T>::Type>
-{
-};
-
 } /* namespace mozilla */
 
 #endif /* mozilla_TypeTraits_h */
--- a/mfbt/tests/TestTuple.cpp
+++ b/mfbt/tests/TestTuple.cpp
@@ -231,31 +231,25 @@ TestGet()
   CHECK(Get<0>(tuple) == 41);
 
   // Writing through reference elements
   Get<1>(tuple) = 42;
   CHECK(Get<1>(tuple) == 42);
   CHECK(y == 42);
 }
 
-static void
+static bool
 TestMakeTuple()
 {
   auto tuple = MakeTuple(42, 0.5f, 'c');
   CHECK_TYPE(tuple, Tuple<int, float, char>);
   CHECK(Get<0>(tuple) == 42);
   CHECK(Get<1>(tuple) == 0.5f);
   CHECK(Get<2>(tuple) == 'c');
-
-  // Make sure we don't infer the type to be Tuple<int&>.
-  int x = 1;
-  auto tuple2 = MakeTuple(x);
-  CHECK_TYPE(tuple2, Tuple<int>);
-  x = 2;
-  CHECK(Get<0>(tuple2) == 1);
+  return true;
 }
 
 static bool
 TestTie()
 {
   int i;
   float f;
   char c;
--- a/mfbt/tests/TestTypeTraits.cpp
+++ b/mfbt/tests/TestTypeTraits.cpp
@@ -3,21 +3,18 @@
 /* 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/. */
 
 #include "mozilla/Assertions.h"
 #include "mozilla/TypeTraits.h"
 
 using mozilla::AddLvalueReference;
-using mozilla::AddPointer;
 using mozilla::AddRvalueReference;
-using mozilla::Decay;
 using mozilla::DeclVal;
-using mozilla::IsFunction;
 using mozilla::IsArray;
 using mozilla::IsBaseOf;
 using mozilla::IsClass;
 using mozilla::IsConvertible;
 using mozilla::IsEmpty;
 using mozilla::IsLvalueReference;
 using mozilla::IsPointer;
 using mozilla::IsReference;
@@ -25,23 +22,16 @@ using mozilla::IsRvalueReference;
 using mozilla::IsSame;
 using mozilla::IsSigned;
 using mozilla::IsUnsigned;
 using mozilla::MakeSigned;
 using mozilla::MakeUnsigned;
 using mozilla::RemoveExtent;
 using mozilla::RemovePointer;
 
-static_assert(!IsFunction<int>::value,
-              "int is not a function type");
-static_assert(IsFunction<void(int)>::value,
-              "void(int) is a function type");
-static_assert(!IsFunction<void(*)(int)>::value,
-              "void(*)(int) is not a function type");
-
 static_assert(!IsArray<bool>::value,
               "bool not an array");
 static_assert(IsArray<bool[]>::value,
               "bool[] is an array");
 static_assert(IsArray<bool[5]>::value,
               "bool[5] is an array");
 
 static_assert(!IsPointer<bool>::value,
@@ -494,46 +484,16 @@ static_assert(IsSame<RemovePointer<void 
                                    void (TestRemovePointer::*)()>::value,
               "removing pointer from void (S::*)() must return void (S::*)()");
 static_assert(IsSame<RemovePointer<void (*)()>::Type, void()>::value,
               "removing pointer from void (*)() must return void()");
 static_assert(IsSame<RemovePointer<bool TestRemovePointer::*>::Type,
                                    bool TestRemovePointer::*>::value,
               "removing pointer from bool S::* must return bool S::*");
 
-static_assert(IsSame<AddPointer<int>::Type, int*>::value,
-              "adding pointer to int must return int*");
-static_assert(IsSame<AddPointer<int*>::Type, int**>::value,
-              "adding pointer to int* must return int**");
-static_assert(IsSame<AddPointer<int&>::Type, int*>::value,
-              "adding pointer to int& must return int*");
-static_assert(IsSame<AddPointer<int* const>::Type, int* const*>::value,
-              "adding pointer to int* const must return int* const*");
-static_assert(IsSame<AddPointer<int* volatile>::Type, int* volatile*>::value,
-              "adding pointer to int* volatile must return int* volatile*");
-
-static_assert(IsSame<Decay<int>::Type, int>::value,
-              "decaying int must return int");
-static_assert(IsSame<Decay<int*>::Type, int*>::value,
-              "decaying int* must return int*");
-static_assert(IsSame<Decay<int* const>::Type, int*>::value,
-              "decaying int* const must return int*");
-static_assert(IsSame<Decay<int* volatile>::Type, int*>::value,
-              "decaying int* volatile must return int*");
-static_assert(IsSame<Decay<int&>::Type, int>::value,
-              "decaying int& must return int");
-static_assert(IsSame<Decay<const int&>::Type, int>::value,
-              "decaying const int& must return int");
-static_assert(IsSame<Decay<int&&>::Type, int>::value,
-              "decaying int&& must return int");
-static_assert(IsSame<Decay<int[1]>::Type, int*>::value,
-              "decaying int[1] must return int*");
-static_assert(IsSame<Decay<void(int)>::Type, void(*)(int)>::value,
-              "decaying void(int) must return void(*)(int)");
-
 /*
  * Android's broken [u]intptr_t inttype macros are broken because its PRI*PTR
  * macros are defined as "ld", but sizeof(long) is 8 and sizeof(intptr_t)
  * is 4 on 32-bit Android. We redefine Android's PRI*PTR macros in
  * IntegerPrintfMacros.h and assert here that our new definitions match the
  * actual type sizes seen at compile time.
  */
 #if defined(ANDROID) && !defined(__LP64__)
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -897,17 +897,17 @@ void nsBaseWidget::ConfigureAPZCTreeMana
   mAPZEventState = new APZEventState(this, mozilla::Move(callback));
 
   mSetAllowedTouchBehaviorCallback = [treeManager](uint64_t aInputBlockId,
                                                    const nsTArray<TouchBehaviorFlags>& aFlags)
   {
     MOZ_ASSERT(NS_IsMainThread());
     APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
         treeManager.get(), &APZCTreeManager::SetAllowedTouchBehavior,
-        aInputBlockId, nsTArray<TouchBehaviorFlags>(aFlags)));
+        aInputBlockId, aFlags));
   };
 
   RefPtr<GeckoContentController> controller = CreateRootContentController();
   if (controller) {
     uint64_t rootLayerTreeId = mCompositorParent->RootLayerTreeId();
     CompositorParent::SetControllerForLayerTree(rootLayerTreeId, controller);
   }
 
@@ -929,17 +929,17 @@ void nsBaseWidget::ConfigureAPZControlle
 void
 nsBaseWidget::SetConfirmedTargetAPZC(uint64_t aInputBlockId,
                                      const nsTArray<ScrollableLayerGuid>& aTargets) const
 {
   // Need to specifically bind this since it's overloaded.
   void (APZCTreeManager::*setTargetApzcFunc)(uint64_t, const nsTArray<ScrollableLayerGuid>&)
           = &APZCTreeManager::SetTargetAPZC;
   APZThreadUtils::RunOnControllerThread(NewRunnableMethod(
-    mAPZC.get(), setTargetApzcFunc, aInputBlockId, nsTArray<ScrollableLayerGuid>(aTargets)));
+    mAPZC.get(), setTargetApzcFunc, aInputBlockId, mozilla::Move(aTargets)));
 }
 
 void
 nsBaseWidget::UpdateZoomConstraints(const uint32_t& aPresShellId,
                                     const FrameMetrics::ViewID& aViewId,
                                     const Maybe<ZoomConstraints>& aConstraints)
 {
   if (!mCompositorParent || !mAPZC) {