LCOV - code coverage report
Current view: top level - mfbt - PodOperations.h (source / functions) Hit Total Coverage
Test: output.info Lines: 36 40 90.0 %
Date: 2017-07-14 16:53:18 Functions: 89 203 43.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : /*
       8             :  * Operations for zeroing POD types, arrays, and so on.
       9             :  *
      10             :  * These operations are preferable to memset, memcmp, and the like because they
      11             :  * don't require remembering to multiply by sizeof(T), array lengths, and so on
      12             :  * everywhere.
      13             :  */
      14             : 
      15             : #ifndef mozilla_PodOperations_h
      16             : #define mozilla_PodOperations_h
      17             : 
      18             : #include "mozilla/Array.h"
      19             : #include "mozilla/ArrayUtils.h"
      20             : #include "mozilla/Attributes.h"
      21             : 
      22             : #include <stdint.h>
      23             : #include <string.h>
      24             : 
      25             : namespace mozilla {
      26             : 
      27             : /** Set the contents of |aT| to 0. */
      28             : template<typename T>
      29             : static MOZ_ALWAYS_INLINE void
      30       88419 : PodZero(T* aT)
      31             : {
      32       88419 :   memset(aT, 0, sizeof(T));
      33       88419 : }
      34             : 
      35             : /** Set the contents of |aNElem| elements starting at |aT| to 0. */
      36             : template<typename T>
      37             : static MOZ_ALWAYS_INLINE void
      38        7382 : PodZero(T* aT, size_t aNElem)
      39             : {
      40             :   /*
      41             :    * This function is often called with 'aNElem' small; we use an inline loop
      42             :    * instead of calling 'memset' with a non-constant length.  The compiler
      43             :    * should inline the memset call with constant size, though.
      44             :    */
      45      393837 :   for (T* end = aT + aNElem; aT < end; aT++) {
      46      386455 :     memset(aT, 0, sizeof(T));
      47             :   }
      48        7382 : }
      49             : 
      50             : /*
      51             :  * Arrays implicitly convert to pointers to their first element, which is
      52             :  * dangerous when combined with the above PodZero definitions.  Adding an
      53             :  * overload for arrays is ambiguous, so we need another identifier.  The
      54             :  * ambiguous overload is left to catch mistaken uses of PodZero; if you get a
      55             :  * compile error involving PodZero and array types, use PodArrayZero instead.
      56             :  */
      57             : template<typename T, size_t N>
      58             : static void PodZero(T (&aT)[N]) = delete;
      59             : template<typename T, size_t N>
      60             : static void PodZero(T (&aT)[N], size_t aNElem) = delete;
      61             : 
      62             : /** Set the contents of the array |aT| to zero. */
      63             : template <class T, size_t N>
      64             : static MOZ_ALWAYS_INLINE void
      65        9448 : PodArrayZero(T (&aT)[N])
      66             : {
      67        9448 :   memset(aT, 0, N * sizeof(T));
      68        9448 : }
      69             : 
      70             : template <typename T, size_t N>
      71             : static MOZ_ALWAYS_INLINE void
      72          52 : PodArrayZero(Array<T, N>& aArr)
      73             : {
      74          52 :   memset(&aArr[0], 0, N * sizeof(T));
      75          52 : }
      76             : 
      77             : /**
      78             :  * Assign |*aSrc| to |*aDst|.  The locations must not be the same and must not
      79             :  * overlap.
      80             :  */
      81             : template<typename T>
      82             : static MOZ_ALWAYS_INLINE void
      83     2427125 : PodAssign(T* aDst, const T* aSrc)
      84             : {
      85     2427125 :   MOZ_ASSERT(aDst + 1 <= aSrc || aSrc + 1 <= aDst,
      86             :              "destination and source must not overlap");
      87     2427125 :   memcpy(reinterpret_cast<char*>(aDst), reinterpret_cast<const char*>(aSrc),
      88             :          sizeof(T));
      89     2427125 : }
      90             : 
      91             : /**
      92             :  * Copy |aNElem| T elements from |aSrc| to |aDst|.  The two memory ranges must
      93             :  * not overlap!
      94             :  */
      95             : template<typename T>
      96             : static MOZ_ALWAYS_INLINE void
      97      188372 : PodCopy(T* aDst, const T* aSrc, size_t aNElem)
      98             : {
      99      188372 :   MOZ_ASSERT(aDst + aNElem <= aSrc || aSrc + aNElem <= aDst,
     100             :              "destination and source must not overlap");
     101      188372 :   if (aNElem < 128) {
     102             :     /*
     103             :      * Avoid using operator= in this loop, as it may have been
     104             :      * intentionally deleted by the POD type.
     105             :      */
     106     2608279 :     for (const T* srcend = aSrc + aNElem; aSrc < srcend; aSrc++, aDst++) {
     107     2423290 :       PodAssign(aDst, aSrc);
     108             :     }
     109             :   } else {
     110        3383 :     memcpy(aDst, aSrc, aNElem * sizeof(T));
     111             :   }
     112      188372 : }
     113             : 
     114             : template<typename T>
     115             : static MOZ_ALWAYS_INLINE void
     116             : PodCopy(volatile T* aDst, const volatile T* aSrc, size_t aNElem)
     117             : {
     118             :   MOZ_ASSERT(aDst + aNElem <= aSrc || aSrc + aNElem <= aDst,
     119             :              "destination and source must not overlap");
     120             : 
     121             :   /*
     122             :    * Volatile |aDst| requires extra work, because it's undefined behavior to
     123             :    * modify volatile objects using the mem* functions.  Just write out the
     124             :    * loops manually, using operator= rather than memcpy for the same reason,
     125             :    * and let the compiler optimize to the extent it can.
     126             :    */
     127             :   for (const volatile T* srcend = aSrc + aNElem;
     128             :        aSrc < srcend;
     129             :        aSrc++, aDst++) {
     130             :     *aDst = *aSrc;
     131             :   }
     132             : }
     133             : 
     134             : /*
     135             :  * Copy the contents of the array |aSrc| into the array |aDst|, both of size N.
     136             :  * The arrays must not overlap!
     137             :  */
     138             : template <class T, size_t N>
     139             : static MOZ_ALWAYS_INLINE void
     140             : PodArrayCopy(T (&aDst)[N], const T (&aSrc)[N])
     141             : {
     142             :   PodCopy(aDst, aSrc, N);
     143             : }
     144             : 
     145             : /**
     146             :  * Copy the memory for |aNElem| T elements from |aSrc| to |aDst|.  If the two
     147             :  * memory ranges overlap, then the effect is as if the |aNElem| elements are
     148             :  * first copied from |aSrc| to a temporary array, and then from the temporary
     149             :  * array to |aDst|.
     150             :  */
     151             : template<typename T>
     152             : static MOZ_ALWAYS_INLINE void
     153           0 : PodMove(T* aDst, const T* aSrc, size_t aNElem)
     154             : {
     155           0 :   MOZ_ASSERT(aNElem <= SIZE_MAX / sizeof(T),
     156             :              "trying to move an impossible number of elements");
     157           0 :   memmove(aDst, aSrc, aNElem * sizeof(T));
     158           0 : }
     159             : 
     160             : /**
     161             :  * Determine whether the |len| elements at |one| are memory-identical to the
     162             :  * |len| elements at |two|.
     163             :  */
     164             : template<typename T>
     165             : static MOZ_ALWAYS_INLINE bool
     166      238881 : PodEqual(const T* one, const T* two, size_t len)
     167             : {
     168      238881 :   if (len < 128) {
     169      233257 :     const T* p1end = one + len;
     170      233257 :     const T* p1 = one;
     171      233257 :     const T* p2 = two;
     172     5644751 :     for (; p1 < p1end; p1++, p2++) {
     173     2707022 :       if (*p1 != *p2) {
     174        1275 :         return false;
     175             :       }
     176             :     }
     177      231982 :     return true;
     178             :   }
     179             : 
     180        5624 :   return !memcmp(one, two, len * sizeof(T));
     181             : }
     182             : 
     183             : /*
     184             :  * Determine whether the |N| elements at |one| are memory-identical to the
     185             :  * |N| elements at |two|.
     186             :  */
     187             : template <class T, size_t N>
     188             : static MOZ_ALWAYS_INLINE bool
     189          83 : PodEqual(const T (&one)[N], const T (&two)[N])
     190             : {
     191          83 :   return PodEqual(one, two, N);
     192             : }
     193             : 
     194             : } // namespace mozilla
     195             : 
     196             : #endif /* mozilla_PodOperations_h */

Generated by: LCOV version 1.13