Index: src/core/SkChecksum.h |
diff --git a/src/core/SkChecksum.h b/src/core/SkChecksum.h |
index fe1e9584a20e8e87c2475a648af21e03db9e6710..9f2ebf460aff1ed778183f1480a15f42b0dd1315 100644 |
--- a/src/core/SkChecksum.h |
+++ b/src/core/SkChecksum.h |
@@ -62,12 +62,18 @@ public: |
* @return hash result |
*/ |
static uint32_t Murmur3(const uint32_t* data, size_t bytes, uint32_t seed=0) { |
+ // Use may_alias to remind the compiler we're intentionally violating strict aliasing, |
+ // and so not to apply strict-aliasing-based optimizations. |
+ typedef uint32_t SK_ATTRIBUTE(may_alias) aliased_uint32_t; |
+ const aliased_uint32_t* safe_data = (const aliased_uint32_t*)data; |
+ |
SkASSERTF(SkIsAlign4(bytes), "Expected 4-byte multiple, got %zu", bytes); |
const size_t words = bytes/4; |
+ |
uint32_t hash = seed; |
for (size_t i = 0; i < words; i++) { |
- uint32_t k = data[i]; |
+ uint32_t k = safe_data[i]; |
k *= 0xcc9e2d51; |
k = (k << 15) | (k >> 17); |
k *= 0x1b873593; |
@@ -95,6 +101,11 @@ public: |
* @return checksum result |
*/ |
static uint32_t Compute(const uint32_t* data, size_t size) { |
+ // Use may_alias to remind the compiler we're intentionally violating strict aliasing, |
+ // and so not to apply strict-aliasing-based optimizations. |
+ typedef uint32_t SK_ATTRIBUTE(may_alias) aliased_uint32_t; |
+ const aliased_uint32_t* safe_data = (const aliased_uint32_t*)data; |
+ |
SkASSERT(SkIsAlign4(size)); |
/* |
@@ -104,7 +115,7 @@ public: |
* sizeof()). |
*/ |
uintptr_t result = 0; |
- const uintptr_t* ptr = reinterpret_cast<const uintptr_t*>(data); |
+ const uintptr_t* ptr = reinterpret_cast<const uintptr_t*>(safe_data); |
/* |
* count the number of quad element chunks. This takes into account |
@@ -120,10 +131,10 @@ public: |
} |
size &= ((sizeof(uintptr_t) << 2) - 1); |
- data = reinterpret_cast<const uint32_t*>(ptr); |
- const uint32_t* stop = data + (size >> 2); |
- while (data < stop) { |
- result = Mash(result, *data++); |
+ safe_data = reinterpret_cast<const aliased_uint32_t*>(ptr); |
+ const aliased_uint32_t* stop = safe_data + (size >> 2); |
+ while (safe_data < stop) { |
+ result = Mash(result, *safe_data++); |
} |
/* |