mfbt/Alignment.h

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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/. */
     7 /* Functionality related to memory alignment. */
     9 #ifndef mozilla_Alignment_h
    10 #define mozilla_Alignment_h
    12 #include <stddef.h>
    13 #include <stdint.h>
    15 namespace mozilla {
    17 /*
    18  * This class, and the corresponding macro MOZ_ALIGNOF, figures out how many
    19  * bytes of alignment a given type needs.
    20  */
    21 template<typename T>
    22 class AlignmentFinder
    23 {
    24     struct Aligner
    25     {
    26         char c;
    27         T t;
    28     };
    30   public:
    31     static const size_t alignment = sizeof(Aligner) - sizeof(T);
    32 };
    34 #define MOZ_ALIGNOF(T) mozilla::AlignmentFinder<T>::alignment
    36 /*
    37  * Declare the MOZ_ALIGNED_DECL macro for declaring aligned types.
    38  *
    39  * For instance,
    40  *
    41  *   MOZ_ALIGNED_DECL(char arr[2], 8);
    42  *
    43  * will declare a two-character array |arr| aligned to 8 bytes.
    44  */
    46 #if defined(__GNUC__)
    47 #  define MOZ_ALIGNED_DECL(_type, _align) \
    48      _type __attribute__((aligned(_align)))
    49 #elif defined(_MSC_VER)
    50 #  define MOZ_ALIGNED_DECL(_type, _align) \
    51      __declspec(align(_align)) _type
    52 #else
    53 #  warning "We don't know how to align variables on this compiler."
    54 #  define MOZ_ALIGNED_DECL(_type, _align) _type
    55 #endif
    57 /*
    58  * AlignedElem<N> is a structure whose alignment is guaranteed to be at least N
    59  * bytes.
    60  *
    61  * We support 1, 2, 4, 8, and 16-bit alignment.
    62  */
    63 template<size_t Align>
    64 struct AlignedElem;
    66 /*
    67  * We have to specialize this template because GCC doesn't like __attribute__((aligned(foo))) where
    68  * foo is a template parameter.
    69  */
    71 template<>
    72 struct AlignedElem<1>
    73 {
    74     MOZ_ALIGNED_DECL(uint8_t elem, 1);
    75 };
    77 template<>
    78 struct AlignedElem<2>
    79 {
    80     MOZ_ALIGNED_DECL(uint8_t elem, 2);
    81 };
    83 template<>
    84 struct AlignedElem<4>
    85 {
    86     MOZ_ALIGNED_DECL(uint8_t elem, 4);
    87 };
    89 template<>
    90 struct AlignedElem<8>
    91 {
    92     MOZ_ALIGNED_DECL(uint8_t elem, 8);
    93 };
    95 template<>
    96 struct AlignedElem<16>
    97 {
    98     MOZ_ALIGNED_DECL(uint8_t elem, 16);
    99 };
   101 /*
   102  * This utility pales in comparison to Boost's aligned_storage. The utility
   103  * simply assumes that uint64_t is enough alignment for anyone. This may need
   104  * to be extended one day...
   105  *
   106  * As an important side effect, pulling the storage into this template is
   107  * enough obfuscation to confuse gcc's strict-aliasing analysis into not giving
   108  * false negatives when we cast from the char buffer to whatever type we've
   109  * constructed using the bytes.
   110  */
   111 template<size_t Nbytes>
   112 struct AlignedStorage
   113 {
   114     union U {
   115       char bytes[Nbytes];
   116       uint64_t _;
   117     } u;
   119     const void* addr() const { return u.bytes; }
   120     void* addr() { return u.bytes; }
   121 };
   123 template<typename T>
   124 struct AlignedStorage2
   125 {
   126     union U {
   127       char bytes[sizeof(T)];
   128       uint64_t _;
   129     } u;
   131     const T* addr() const { return reinterpret_cast<const T*>(u.bytes); }
   132     T* addr() { return static_cast<T*>(static_cast<void*>(u.bytes)); }
   133 };
   135 } /* namespace mozilla */
   137 #endif /* mozilla_Alignment_h */

mercurial