Bug 1039924 part 4 - Fill out TimeDurationValueCalculator and use it; r=froydnj
authorBrian Birtles <birtles@gmail.com>
Thu, 25 Sep 2014 14:25:49 +0900
changeset 222592 82fbeb45b3d6bb6560ca4ee15138dcc46a2982bf
parent 222591 af942cc33a8385e684ecc850f74af424482211b3
child 222593 2dd874cbd5f794bbfb6879c14464ef03018275ab
push id7107
push userraliiev@mozilla.com
push dateMon, 13 Oct 2014 17:43:31 +0000
treeherdermozilla-aurora@b4b34e0acc75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1039924
milestone35.0a1
Bug 1039924 part 4 - Fill out TimeDurationValueCalculator and use it; r=froydnj This patch builds on the templatization from the previous patch to move arithmetic on the mValue member of BaseTimeDuration to the ValueCalculator template parameter.
xpcom/ds/TimeStamp.h
--- a/xpcom/ds/TimeStamp.h
+++ b/xpcom/ds/TimeStamp.h
@@ -6,16 +6,17 @@
 
 #ifndef mozilla_TimeStamp_h
 #define mozilla_TimeStamp_h
 
 #include <stdint.h>
 #include "mozilla/Assertions.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/FloatingPoint.h"
+#include "mozilla/TypeTraits.h"
 #include "nscore.h"
 #include "nsDebug.h"
 
 namespace IPC {
 template<typename T> struct ParamTraits;
 }
 
 #ifdef XP_WIN
@@ -138,75 +139,80 @@ public:
 
   static BaseTimeDuration Forever()
   {
     return FromTicks(INT64_MAX);
   }
 
   BaseTimeDuration operator+(const BaseTimeDuration& aOther) const
   {
-    return FromTicks(mValue + aOther.mValue);
+    return FromTicks(ValueCalculator::Add(mValue, aOther.mValue));
   }
   BaseTimeDuration operator-(const BaseTimeDuration& aOther) const
   {
-    return FromTicks(mValue - aOther.mValue);
+    return FromTicks(ValueCalculator::Subtract(mValue, aOther.mValue));
   }
   BaseTimeDuration& operator+=(const BaseTimeDuration& aOther)
   {
-    mValue += aOther.mValue;
+    mValue = ValueCalculator::Add(mValue, aOther.mValue);
     return *this;
   }
   BaseTimeDuration& operator-=(const BaseTimeDuration& aOther)
   {
-    mValue -= aOther.mValue;
+    mValue = ValueCalculator::Subtract(mValue, aOther.mValue);
     return *this;
   }
 
 private:
   // Block double multiplier (slower, imprecise if long duration) - Bug 853398.
   // If required, use MultDouble explicitly and with care.
   BaseTimeDuration operator*(const double aMultiplier) const MOZ_DELETE;
 
 public:
   BaseTimeDuration MultDouble(double aMultiplier) const
   {
-    return FromTicks(static_cast<int64_t>(mValue * aMultiplier));
+    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
   }
   BaseTimeDuration operator*(const int32_t aMultiplier) const
   {
-    return FromTicks(mValue * int64_t(aMultiplier));
+    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
   }
   BaseTimeDuration operator*(const uint32_t aMultiplier) const
   {
-    return FromTicks(mValue * int64_t(aMultiplier));
+    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
   }
   BaseTimeDuration operator*(const int64_t aMultiplier) const
   {
-    return FromTicks(mValue * aMultiplier);
+    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
   }
   BaseTimeDuration operator*(const uint64_t aMultiplier) const
   {
     if (aMultiplier > INT64_MAX) {
       NS_WARNING("Out-of-range multiplier when multiplying BaseTimeDuration");
       return Forever();
     }
-    return FromTicks(mValue * int64_t(aMultiplier));
+    return FromTicks(ValueCalculator::Multiply(mValue, aMultiplier));
   }
   BaseTimeDuration operator/(const int64_t aDivisor) const
   {
-    return FromTicks(mValue / aDivisor);
+    MOZ_ASSERT(aDivisor != 0, "Division by zero");
+    return FromTicks(ValueCalculator::Divide(mValue, aDivisor));
   }
   double operator/(const BaseTimeDuration& aOther) const
   {
-    return static_cast<double>(mValue) / aOther.mValue;
+#ifndef MOZ_B2G
+    // Bug 1066388 - This fails on B2G ICS Emulator
+    MOZ_ASSERT(aOther.mValue != 0, "Division by zero");
+#endif
+    return ValueCalculator::DivideDouble(mValue, aOther.mValue);
   }
   BaseTimeDuration operator%(const BaseTimeDuration& aOther) const
   {
     MOZ_ASSERT(aOther.mValue != 0, "Division by zero");
-    return FromTicks(mValue % aOther.mValue);
+    return FromTicks(ValueCalculator::Modulo(mValue, aOther.mValue));
   }
 
   template<typename E>
   bool operator<(const BaseTimeDuration<E>& aOther) const
   {
     return mValue < aOther.mValue;
   }
   template<typename E>
@@ -278,20 +284,58 @@ private:
 
     return FromTicks(int64_t(aTicks));
   }
 
   // Duration, result is implementation-specific difference of two TimeStamps
   int64_t mValue;
 };
 
-// FIXME: To be filled-in a subsequent patch in this series.
+/**
+ * Perform arithmetic operations on the value of a BaseTimeDuration without
+ * doing strict checks on the range of values.
+ */
 class TimeDurationValueCalculator
-{ };
+{
+public:
+  static int64_t Add(int64_t aA, int64_t aB) { return aA + aB; }
+  static int64_t Subtract(int64_t aA, int64_t aB) { return aA - aB; }
+
+  template <typename T>
+  static int64_t Multiply(int64_t aA, T aB)
+  {
+    static_assert(IsIntegral<T>::value,
+                  "Using integer multiplication routine with non-integer type."
+                  " Further specialization required");
+    return aA * static_cast<int64_t>(aB);
+  }
 
+  static int64_t Divide(int64_t aA, int64_t aB) { return aA / aB; }
+  static double DivideDouble(int64_t aA, int64_t aB)
+  {
+    return static_cast<double>(aA) / aB;
+  }
+  static int64_t Modulo(int64_t aA, int64_t aB) { return aA % aB; }
+};
+
+template <>
+inline int64_t
+TimeDurationValueCalculator::Multiply<double>(int64_t aA, double aB)
+{
+  return static_cast<int64_t>(aA * aB);
+}
+
+/**
+ * Specialization of BaseTimeDuration that uses TimeDurationValueCalculator for
+ * arithmetic on the mValue member.
+ *
+ * Use this class for time durations that are *not* expected to hold values of
+ * Forever (or the negative equivalent) or when such time duration are *not*
+ * expected to be used in arithmetic operations.
+ */
 typedef BaseTimeDuration<TimeDurationValueCalculator> TimeDuration;
 
 /**
  * Instances of this class represent moments in time, or a special
  * "null" moment. We do not use the non-monotonic system clock or
  * local time, since they can be reset, causing apparent backward
  * travel in time, which can confuse algorithms. Instead we measure
  * elapsed time according to the system.  This time can never go