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 | * Copyright 2012 Google Inc. |
michael@0 | 3 | * |
michael@0 | 4 | * Use of this source code is governed by a BSD-style license that can be |
michael@0 | 5 | * found in the LICENSE file. |
michael@0 | 6 | */ |
michael@0 | 7 | |
michael@0 | 8 | #ifndef SkChecksum_DEFINED |
michael@0 | 9 | #define SkChecksum_DEFINED |
michael@0 | 10 | |
michael@0 | 11 | #include "SkTypes.h" |
michael@0 | 12 | |
michael@0 | 13 | /** |
michael@0 | 14 | * Computes a 32bit checksum from a blob of 32bit aligned data. This is meant |
michael@0 | 15 | * to be very very fast, as it is used internally by the font cache, in |
michael@0 | 16 | * conjuction with the entire raw key. This algorithm does not generate |
michael@0 | 17 | * unique values as well as others (e.g. MD5) but it performs much faster. |
michael@0 | 18 | * Skia's use cases can survive non-unique values (since the entire key is |
michael@0 | 19 | * always available). Clients should only be used in circumstances where speed |
michael@0 | 20 | * over uniqueness is at a premium. |
michael@0 | 21 | */ |
michael@0 | 22 | class SkChecksum : SkNoncopyable { |
michael@0 | 23 | private: |
michael@0 | 24 | /* |
michael@0 | 25 | * Our Rotate and Mash helpers are meant to automatically do the right |
michael@0 | 26 | * thing depending if sizeof(uintptr_t) is 4 or 8. |
michael@0 | 27 | */ |
michael@0 | 28 | enum { |
michael@0 | 29 | ROTR = 17, |
michael@0 | 30 | ROTL = sizeof(uintptr_t) * 8 - ROTR, |
michael@0 | 31 | HALFBITS = sizeof(uintptr_t) * 4 |
michael@0 | 32 | }; |
michael@0 | 33 | |
michael@0 | 34 | static inline uintptr_t Mash(uintptr_t total, uintptr_t value) { |
michael@0 | 35 | return ((total >> ROTR) | (total << ROTL)) ^ value; |
michael@0 | 36 | } |
michael@0 | 37 | |
michael@0 | 38 | public: |
michael@0 | 39 | |
michael@0 | 40 | /** |
michael@0 | 41 | * Calculate 32-bit Murmur hash (murmur3). |
michael@0 | 42 | * This should take 2-3x longer than SkChecksum::Compute, but is a considerably better hash. |
michael@0 | 43 | * See en.wikipedia.org/wiki/MurmurHash. |
michael@0 | 44 | * |
michael@0 | 45 | * @param data Memory address of the data block to be processed. Must be 32-bit aligned. |
michael@0 | 46 | * @param size Size of the data block in bytes. Must be a multiple of 4. |
michael@0 | 47 | * @param seed Initial hash seed. (optional) |
michael@0 | 48 | * @return hash result |
michael@0 | 49 | */ |
michael@0 | 50 | static uint32_t Murmur3(const uint32_t* data, size_t bytes, uint32_t seed=0) { |
michael@0 | 51 | SkASSERT(SkIsAlign4(bytes)); |
michael@0 | 52 | const size_t words = bytes/4; |
michael@0 | 53 | |
michael@0 | 54 | uint32_t hash = seed; |
michael@0 | 55 | for (size_t i = 0; i < words; i++) { |
michael@0 | 56 | uint32_t k = data[i]; |
michael@0 | 57 | k *= 0xcc9e2d51; |
michael@0 | 58 | k = (k << 15) | (k >> 17); |
michael@0 | 59 | k *= 0x1b873593; |
michael@0 | 60 | |
michael@0 | 61 | hash ^= k; |
michael@0 | 62 | hash = (hash << 13) | (hash >> 19); |
michael@0 | 63 | hash *= 5; |
michael@0 | 64 | hash += 0xe6546b64; |
michael@0 | 65 | } |
michael@0 | 66 | hash ^= bytes; |
michael@0 | 67 | hash ^= hash >> 16; |
michael@0 | 68 | hash *= 0x85ebca6b; |
michael@0 | 69 | hash ^= hash >> 13; |
michael@0 | 70 | hash *= 0xc2b2ae35; |
michael@0 | 71 | hash ^= hash >> 16; |
michael@0 | 72 | return hash; |
michael@0 | 73 | } |
michael@0 | 74 | |
michael@0 | 75 | /** |
michael@0 | 76 | * Compute a 32-bit checksum for a given data block |
michael@0 | 77 | * |
michael@0 | 78 | * WARNING: this algorithm is tuned for efficiency, not backward/forward |
michael@0 | 79 | * compatibility. It may change at any time, so a checksum generated with |
michael@0 | 80 | * one version of the Skia code may not match a checksum generated with |
michael@0 | 81 | * a different version of the Skia code. |
michael@0 | 82 | * |
michael@0 | 83 | * @param data Memory address of the data block to be processed. Must be |
michael@0 | 84 | * 32-bit aligned. |
michael@0 | 85 | * @param size Size of the data block in bytes. Must be a multiple of 4. |
michael@0 | 86 | * @return checksum result |
michael@0 | 87 | */ |
michael@0 | 88 | static uint32_t Compute(const uint32_t* data, size_t size) { |
michael@0 | 89 | SkASSERT(SkIsAlign4(size)); |
michael@0 | 90 | |
michael@0 | 91 | /* |
michael@0 | 92 | * We want to let the compiler use 32bit or 64bit addressing and math |
michael@0 | 93 | * so we use uintptr_t as our magic type. This makes the code a little |
michael@0 | 94 | * more obscure (we can't hard-code 32 or 64 anywhere, but have to use |
michael@0 | 95 | * sizeof()). |
michael@0 | 96 | */ |
michael@0 | 97 | uintptr_t result = 0; |
michael@0 | 98 | const uintptr_t* ptr = reinterpret_cast<const uintptr_t*>(data); |
michael@0 | 99 | |
michael@0 | 100 | /* |
michael@0 | 101 | * count the number of quad element chunks. This takes into account |
michael@0 | 102 | * if we're on a 32bit or 64bit arch, since we use sizeof(uintptr_t) |
michael@0 | 103 | * to compute how much to shift-down the size. |
michael@0 | 104 | */ |
michael@0 | 105 | size_t n4 = size / (sizeof(uintptr_t) << 2); |
michael@0 | 106 | for (size_t i = 0; i < n4; ++i) { |
michael@0 | 107 | result = Mash(result, *ptr++); |
michael@0 | 108 | result = Mash(result, *ptr++); |
michael@0 | 109 | result = Mash(result, *ptr++); |
michael@0 | 110 | result = Mash(result, *ptr++); |
michael@0 | 111 | } |
michael@0 | 112 | size &= ((sizeof(uintptr_t) << 2) - 1); |
michael@0 | 113 | |
michael@0 | 114 | data = reinterpret_cast<const uint32_t*>(ptr); |
michael@0 | 115 | const uint32_t* stop = data + (size >> 2); |
michael@0 | 116 | while (data < stop) { |
michael@0 | 117 | result = Mash(result, *data++); |
michael@0 | 118 | } |
michael@0 | 119 | |
michael@0 | 120 | /* |
michael@0 | 121 | * smash us down to 32bits if we were 64. Note that when uintptr_t is |
michael@0 | 122 | * 32bits, this code-path should go away, but I still got a warning |
michael@0 | 123 | * when I wrote |
michael@0 | 124 | * result ^= result >> 32; |
michael@0 | 125 | * since >>32 is undefined for 32bit ints, hence the wacky HALFBITS |
michael@0 | 126 | * define. |
michael@0 | 127 | */ |
michael@0 | 128 | if (8 == sizeof(result)) { |
michael@0 | 129 | result ^= result >> HALFBITS; |
michael@0 | 130 | } |
michael@0 | 131 | return static_cast<uint32_t>(result); |
michael@0 | 132 | } |
michael@0 | 133 | }; |
michael@0 | 134 | |
michael@0 | 135 | #endif |