Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | |
michael@0 | 2 | /* |
michael@0 | 3 | * Copyright 2006 The Android Open Source Project |
michael@0 | 4 | * |
michael@0 | 5 | * Use of this source code is governed by a BSD-style license that can be |
michael@0 | 6 | * found in the LICENSE file. |
michael@0 | 7 | */ |
michael@0 | 8 | |
michael@0 | 9 | |
michael@0 | 10 | #ifndef SkMath_DEFINED |
michael@0 | 11 | #define SkMath_DEFINED |
michael@0 | 12 | |
michael@0 | 13 | #include "SkTypes.h" |
michael@0 | 14 | |
michael@0 | 15 | /** |
michael@0 | 16 | * Computes numer1 * numer2 / denom in full 64 intermediate precision. |
michael@0 | 17 | * It is an error for denom to be 0. There is no special handling if |
michael@0 | 18 | * the result overflows 32bits. |
michael@0 | 19 | */ |
michael@0 | 20 | int32_t SkMulDiv(int32_t numer1, int32_t numer2, int32_t denom); |
michael@0 | 21 | |
michael@0 | 22 | /** |
michael@0 | 23 | * Computes (numer1 << shift) / denom in full 64 intermediate precision. |
michael@0 | 24 | * It is an error for denom to be 0. There is no special handling if |
michael@0 | 25 | * the result overflows 32bits. |
michael@0 | 26 | */ |
michael@0 | 27 | int32_t SkDivBits(int32_t numer, int32_t denom, int shift); |
michael@0 | 28 | |
michael@0 | 29 | /** |
michael@0 | 30 | * Return the integer square root of value, with a bias of bitBias |
michael@0 | 31 | */ |
michael@0 | 32 | int32_t SkSqrtBits(int32_t value, int bitBias); |
michael@0 | 33 | |
michael@0 | 34 | /** Return the integer square root of n, treated as a SkFixed (16.16) |
michael@0 | 35 | */ |
michael@0 | 36 | #define SkSqrt32(n) SkSqrtBits(n, 15) |
michael@0 | 37 | |
michael@0 | 38 | // 64bit -> 32bit utilities |
michael@0 | 39 | |
michael@0 | 40 | /** |
michael@0 | 41 | * Return true iff the 64bit value can exactly be represented in signed 32bits |
michael@0 | 42 | */ |
michael@0 | 43 | static inline bool sk_64_isS32(int64_t value) { |
michael@0 | 44 | return (int32_t)value == value; |
michael@0 | 45 | } |
michael@0 | 46 | |
michael@0 | 47 | /** |
michael@0 | 48 | * Return the 64bit argument as signed 32bits, asserting in debug that the arg |
michael@0 | 49 | * exactly fits in signed 32bits. In the release build, no checks are preformed |
michael@0 | 50 | * and the return value if the arg does not fit is undefined. |
michael@0 | 51 | */ |
michael@0 | 52 | static inline int32_t sk_64_asS32(int64_t value) { |
michael@0 | 53 | SkASSERT(sk_64_isS32(value)); |
michael@0 | 54 | return (int32_t)value; |
michael@0 | 55 | } |
michael@0 | 56 | |
michael@0 | 57 | // Handy util that can be passed two ints, and will automatically promote to |
michael@0 | 58 | // 64bits before the multiply, so the caller doesn't have to remember to cast |
michael@0 | 59 | // e.g. (int64_t)a * b; |
michael@0 | 60 | static inline int64_t sk_64_mul(int64_t a, int64_t b) { |
michael@0 | 61 | return a * b; |
michael@0 | 62 | } |
michael@0 | 63 | |
michael@0 | 64 | /////////////////////////////////////////////////////////////////////////////// |
michael@0 | 65 | |
michael@0 | 66 | //! Returns the number of leading zero bits (0...32) |
michael@0 | 67 | int SkCLZ_portable(uint32_t); |
michael@0 | 68 | |
michael@0 | 69 | #ifndef SkCLZ |
michael@0 | 70 | #if defined(_MSC_VER) && _MSC_VER >= 1400 |
michael@0 | 71 | #include <intrin.h> |
michael@0 | 72 | |
michael@0 | 73 | static inline int SkCLZ(uint32_t mask) { |
michael@0 | 74 | if (mask) { |
michael@0 | 75 | DWORD index; |
michael@0 | 76 | _BitScanReverse(&index, mask); |
michael@0 | 77 | return index ^ 0x1F; |
michael@0 | 78 | } else { |
michael@0 | 79 | return 32; |
michael@0 | 80 | } |
michael@0 | 81 | } |
michael@0 | 82 | #elif defined(SK_CPU_ARM) || defined(__GNUC__) || defined(__clang__) |
michael@0 | 83 | static inline int SkCLZ(uint32_t mask) { |
michael@0 | 84 | // __builtin_clz(0) is undefined, so we have to detect that case. |
michael@0 | 85 | return mask ? __builtin_clz(mask) : 32; |
michael@0 | 86 | } |
michael@0 | 87 | #else |
michael@0 | 88 | #define SkCLZ(x) SkCLZ_portable(x) |
michael@0 | 89 | #endif |
michael@0 | 90 | #endif |
michael@0 | 91 | |
michael@0 | 92 | /** |
michael@0 | 93 | * Returns (value < 0 ? 0 : value) efficiently (i.e. no compares or branches) |
michael@0 | 94 | */ |
michael@0 | 95 | static inline int SkClampPos(int value) { |
michael@0 | 96 | return value & ~(value >> 31); |
michael@0 | 97 | } |
michael@0 | 98 | |
michael@0 | 99 | /** Given an integer and a positive (max) integer, return the value |
michael@0 | 100 | * pinned against 0 and max, inclusive. |
michael@0 | 101 | * @param value The value we want returned pinned between [0...max] |
michael@0 | 102 | * @param max The positive max value |
michael@0 | 103 | * @return 0 if value < 0, max if value > max, else value |
michael@0 | 104 | */ |
michael@0 | 105 | static inline int SkClampMax(int value, int max) { |
michael@0 | 106 | // ensure that max is positive |
michael@0 | 107 | SkASSERT(max >= 0); |
michael@0 | 108 | if (value < 0) { |
michael@0 | 109 | value = 0; |
michael@0 | 110 | } |
michael@0 | 111 | if (value > max) { |
michael@0 | 112 | value = max; |
michael@0 | 113 | } |
michael@0 | 114 | return value; |
michael@0 | 115 | } |
michael@0 | 116 | |
michael@0 | 117 | /** |
michael@0 | 118 | * Returns the smallest power-of-2 that is >= the specified value. If value |
michael@0 | 119 | * is already a power of 2, then it is returned unchanged. It is undefined |
michael@0 | 120 | * if value is <= 0. |
michael@0 | 121 | */ |
michael@0 | 122 | static inline int SkNextPow2(int value) { |
michael@0 | 123 | SkASSERT(value > 0); |
michael@0 | 124 | return 1 << (32 - SkCLZ(value - 1)); |
michael@0 | 125 | } |
michael@0 | 126 | |
michael@0 | 127 | /** |
michael@0 | 128 | * Returns the log2 of the specified value, were that value to be rounded up |
michael@0 | 129 | * to the next power of 2. It is undefined to pass 0. Examples: |
michael@0 | 130 | * SkNextLog2(1) -> 0 |
michael@0 | 131 | * SkNextLog2(2) -> 1 |
michael@0 | 132 | * SkNextLog2(3) -> 2 |
michael@0 | 133 | * SkNextLog2(4) -> 2 |
michael@0 | 134 | * SkNextLog2(5) -> 3 |
michael@0 | 135 | */ |
michael@0 | 136 | static inline int SkNextLog2(uint32_t value) { |
michael@0 | 137 | SkASSERT(value != 0); |
michael@0 | 138 | return 32 - SkCLZ(value - 1); |
michael@0 | 139 | } |
michael@0 | 140 | |
michael@0 | 141 | /** |
michael@0 | 142 | * Returns true if value is a power of 2. Does not explicitly check for |
michael@0 | 143 | * value <= 0. |
michael@0 | 144 | */ |
michael@0 | 145 | static inline bool SkIsPow2(int value) { |
michael@0 | 146 | return (value & (value - 1)) == 0; |
michael@0 | 147 | } |
michael@0 | 148 | |
michael@0 | 149 | /////////////////////////////////////////////////////////////////////////////// |
michael@0 | 150 | |
michael@0 | 151 | /** |
michael@0 | 152 | * SkMulS16(a, b) multiplies a * b, but requires that a and b are both int16_t. |
michael@0 | 153 | * With this requirement, we can generate faster instructions on some |
michael@0 | 154 | * architectures. |
michael@0 | 155 | */ |
michael@0 | 156 | #ifdef SK_ARM_HAS_EDSP |
michael@0 | 157 | static inline int32_t SkMulS16(S16CPU x, S16CPU y) { |
michael@0 | 158 | SkASSERT((int16_t)x == x); |
michael@0 | 159 | SkASSERT((int16_t)y == y); |
michael@0 | 160 | int32_t product; |
michael@0 | 161 | asm("smulbb %0, %1, %2 \n" |
michael@0 | 162 | : "=r"(product) |
michael@0 | 163 | : "r"(x), "r"(y) |
michael@0 | 164 | ); |
michael@0 | 165 | return product; |
michael@0 | 166 | } |
michael@0 | 167 | #else |
michael@0 | 168 | #ifdef SK_DEBUG |
michael@0 | 169 | static inline int32_t SkMulS16(S16CPU x, S16CPU y) { |
michael@0 | 170 | SkASSERT((int16_t)x == x); |
michael@0 | 171 | SkASSERT((int16_t)y == y); |
michael@0 | 172 | return x * y; |
michael@0 | 173 | } |
michael@0 | 174 | #else |
michael@0 | 175 | #define SkMulS16(x, y) ((x) * (y)) |
michael@0 | 176 | #endif |
michael@0 | 177 | #endif |
michael@0 | 178 | |
michael@0 | 179 | /** |
michael@0 | 180 | * Return a*b/((1 << shift) - 1), rounding any fractional bits. |
michael@0 | 181 | * Only valid if a and b are unsigned and <= 32767 and shift is > 0 and <= 8 |
michael@0 | 182 | */ |
michael@0 | 183 | static inline unsigned SkMul16ShiftRound(U16CPU a, U16CPU b, int shift) { |
michael@0 | 184 | SkASSERT(a <= 32767); |
michael@0 | 185 | SkASSERT(b <= 32767); |
michael@0 | 186 | SkASSERT(shift > 0 && shift <= 8); |
michael@0 | 187 | unsigned prod = SkMulS16(a, b) + (1 << (shift - 1)); |
michael@0 | 188 | return (prod + (prod >> shift)) >> shift; |
michael@0 | 189 | } |
michael@0 | 190 | |
michael@0 | 191 | /** |
michael@0 | 192 | * Return a*b/255, rounding any fractional bits. |
michael@0 | 193 | * Only valid if a and b are unsigned and <= 32767. |
michael@0 | 194 | */ |
michael@0 | 195 | static inline U8CPU SkMulDiv255Round(U16CPU a, U16CPU b) { |
michael@0 | 196 | SkASSERT(a <= 32767); |
michael@0 | 197 | SkASSERT(b <= 32767); |
michael@0 | 198 | unsigned prod = SkMulS16(a, b) + 128; |
michael@0 | 199 | return (prod + (prod >> 8)) >> 8; |
michael@0 | 200 | } |
michael@0 | 201 | |
michael@0 | 202 | /** |
michael@0 | 203 | * Stores numer/denom and numer%denom into div and mod respectively. |
michael@0 | 204 | */ |
michael@0 | 205 | template <typename In, typename Out> |
michael@0 | 206 | inline void SkTDivMod(In numer, In denom, Out* div, Out* mod) { |
michael@0 | 207 | #ifdef SK_CPU_ARM |
michael@0 | 208 | // If we wrote this as in the else branch, GCC won't fuse the two into one |
michael@0 | 209 | // divmod call, but rather a div call followed by a divmod. Silly! This |
michael@0 | 210 | // version is just as fast as calling __aeabi_[u]idivmod manually, but with |
michael@0 | 211 | // prettier code. |
michael@0 | 212 | // |
michael@0 | 213 | // This benches as around 2x faster than the code in the else branch. |
michael@0 | 214 | const In d = numer/denom; |
michael@0 | 215 | *div = static_cast<Out>(d); |
michael@0 | 216 | *mod = static_cast<Out>(numer-d*denom); |
michael@0 | 217 | #else |
michael@0 | 218 | // On x86 this will just be a single idiv. |
michael@0 | 219 | *div = static_cast<Out>(numer/denom); |
michael@0 | 220 | *mod = static_cast<Out>(numer%denom); |
michael@0 | 221 | #endif // SK_CPU_ARM |
michael@0 | 222 | } |
michael@0 | 223 | |
michael@0 | 224 | #endif |