Bug 862657 - Make PodCopy work even when copying to a volatile address, and add PodArrayCopy for copying one fixed-size array into another array of the same size. r=froydnj
authorJeff Walden <jwalden@mit.edu>
Mon, 06 May 2013 11:05:52 -0700
changeset 131075 75f047d8b34760a1ef31d9793d07052aab51624d
parent 131074 33a510f4ae926e4da4d0a4907584752137b63fb2
child 131076 83ed83e58666bdf136e3f78d5a0ae75a6f673652
push id24649
push userryanvm@gmail.com
push dateWed, 08 May 2013 02:10:32 +0000
treeherdermozilla-central@b980d32c366f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs862657
milestone23.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 862657 - Make PodCopy work even when copying to a volatile address, and add PodArrayCopy for copying one fixed-size array into another array of the same size. r=froydnj
mfbt/PodOperations.h
--- a/mfbt/PodOperations.h
+++ b/mfbt/PodOperations.h
@@ -96,16 +96,47 @@ PodCopy(T* dst, const T* src, size_t nel
      */
     for (const T* srcend = src + nelem; src < srcend; src++, dst++)
       PodAssign(dst, src);
   } else {
     memcpy(dst, src, nelem * sizeof(T));
   }
 }
 
+template<typename T>
+MOZ_ALWAYS_INLINE static void
+PodCopy(volatile T* dst, const volatile T* src, size_t nelem)
+{
+  MOZ_ASSERT(dst != src);
+  MOZ_ASSERT_IF(src < dst,
+                PointerRangeSize(src, static_cast<const volatile T*>(dst)) >= nelem);
+  MOZ_ASSERT_IF(dst < src,
+                PointerRangeSize(static_cast<const volatile T*>(dst), src) >= nelem);
+
+  /*
+   * Volatile |dst| requires extra work, because it's undefined behavior to
+   * modify volatile objects using the mem* functions.  Just write out the
+   * loops manually, using operator= rather than memcpy for the same reason,
+   * and let the compiler optimize to the extent it can.
+   */
+  for (const volatile T* srcend = src + nelem; src < srcend; src++, dst++)
+    *dst = *src;
+}
+
+/*
+ * Copy the contents of the array |src| into the array |dst|, both of size N.
+ * The arrays must not overlap!
+ */
+template <class T, size_t N>
+static void
+PodArrayCopy(T (&dst)[N], const T (&src)[N])
+{
+  PodCopy(dst, src, N);
+}
+
 /**
  * Determine whether the |len| elements at |one| are memory-identical to the
  * |len| elements at |two|.
  */
 template<typename T>
 MOZ_ALWAYS_INLINE static bool
 PodEqual(const T* one, const T* two, size_t len)
 {