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.

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

mercurial