diff options
author | milko.leporis <milko.leporis@imgtec.com> | 2016-06-05 13:14:21 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-06-05 13:14:21 -0700 |
commit | 401e77cfe126eea1a12bd81410871fdb80739283 (patch) | |
tree | 1904f87310a09ed1eeacf50a70ba73ae9cdc812d | |
parent | 863689c3f468acdd9b9e06e0835c5fd1e2cad4c6 (diff) |
MIPS32r2: Fix Chromium runtime crash
Crash is caused by ldxc1 instruction, which traps when double values are
not aligned on 8-byte boundaries. Problem was tracked to SkChunkAlloc which
produces pointers aligned on 4-byte boundaries leading to misalignment.
This change makes sure that SkChunkAlloc will produce pointers that are
aligned to 8 bytes.
Appropriate tests are added to tests/MemsetTest.cpp
TEST=Build Chromium with Clang and run on MIPS32r2 platform
TEST=./out/Debug/dm --match Memset
BUG=130022
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1849183004
Review-Url: https://codereview.chromium.org/1849183004
-rw-r--r-- | gyp/common_conditions.gypi | 18 | ||||
-rw-r--r-- | include/core/SkChunkAlloc.h | 11 | ||||
-rw-r--r-- | src/core/SkChunkAlloc.cpp | 15 | ||||
-rw-r--r-- | tests/MemsetTest.cpp | 17 |
4 files changed, 47 insertions, 14 deletions
diff --git a/gyp/common_conditions.gypi b/gyp/common_conditions.gypi index 4f387e9883..a9b012406d 100644 --- a/gyp/common_conditions.gypi +++ b/gyp/common_conditions.gypi @@ -306,13 +306,17 @@ ], }], [ '"mips" in skia_arch_type', { - 'cflags': [ '-EL' ], - 'conditions': [ - [ 'mips_arch_variant == "mips32r2"', { - 'cflags': [ '-march=mips32r2' ], - 'conditions': [ - [ 'mips_dsp == 1', { 'cflags': [ '-mdsp' ] }], - [ 'mips_dsp == 2', { 'cflags': [ '-mdspr2' ] }], + 'target_conditions': [ + [ '_toolset == "target"', { + 'cflags' : ['-EL'], + 'conditions' : [ + [ 'mips_arch_variant == "mips32r2"', { + 'cflags': [ '-march=mips32r2' ], + 'conditions': [ + [ 'mips_dsp == 1', { 'cflags': [ '-mdsp' ] }], + [ 'mips_dsp == 2', { 'cflags': [ '-mdspr2' ] }], + ], + }], ], }], ], diff --git a/include/core/SkChunkAlloc.h b/include/core/SkChunkAlloc.h index 9699842e6b..bb4ec8faec 100644 --- a/include/core/SkChunkAlloc.h +++ b/include/core/SkChunkAlloc.h @@ -33,7 +33,18 @@ public: kThrow_AllocFailType }; + /** + * Allocates a memory block of size bytes. + * On success: returns a pointer to beginning of memory block that is + * 8 byte aligned. The content of allocated block is not initialized. + * On failure: calls abort() if called with kThrow_AllocFailType, + * otherwise returns NULL pointer. + */ void* alloc(size_t bytes, AllocFailType); + + /** + * Shortcut for calling alloc with kThrow_AllocFailType. + */ void* allocThrow(size_t bytes) { return this->alloc(bytes, kThrow_AllocFailType); } diff --git a/src/core/SkChunkAlloc.cpp b/src/core/SkChunkAlloc.cpp index 8c5b8fb6a4..bb52c46c7a 100644 --- a/src/core/SkChunkAlloc.cpp +++ b/src/core/SkChunkAlloc.cpp @@ -23,7 +23,7 @@ struct SkChunkAlloc::Block { char* fFreePtr; // data[] follows - size_t blockSize() { + size_t blockSize() const { char* start = this->startOfData(); size_t bytes = fFreePtr - start; return fFreeSize + bytes; @@ -35,8 +35,8 @@ struct SkChunkAlloc::Block { fFreePtr = this->startOfData(); } - char* startOfData() { - return reinterpret_cast<char*>(this + 1); + char* startOfData() const { + return reinterpret_cast<char*>(SkAlign8(reinterpret_cast<size_t>(this + 1))); } static void FreeChain(Block* block) { @@ -49,7 +49,7 @@ struct SkChunkAlloc::Block { bool contains(const void* addr) const { const char* ptr = reinterpret_cast<const char*>(addr); - return ptr >= (const char*)(this + 1) && ptr < fFreePtr; + return ptr >= this->startOfData() && ptr < fFreePtr; } }; @@ -121,7 +121,7 @@ SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) { size = fChunkSize; } - Block* block = (Block*)sk_malloc_flags(sizeof(Block) + size, + Block* block = (Block*)sk_malloc_flags(SkAlign8(sizeof(Block)) + size, ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0); if (block) { @@ -137,7 +137,7 @@ SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) { } SkChunkAlloc::Block* SkChunkAlloc::addBlockIfNecessary(size_t bytes, AllocFailType ftype) { - SkASSERT(SkIsAlign4(bytes)); + SkASSERT(SkIsAlign8(bytes)); if (!fBlock || bytes > fBlock->fFreeSize) { Block* block = this->newBlock(bytes, ftype); @@ -160,7 +160,7 @@ SkChunkAlloc::Block* SkChunkAlloc::addBlockIfNecessary(size_t bytes, AllocFailTy void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) { SkDEBUGCODE(this->validate();) - bytes = SkAlign4(bytes); + bytes = SkAlign8(bytes); Block* block = this->addBlockIfNecessary(bytes, ftype); if (!block) { @@ -173,6 +173,7 @@ void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) { block->fFreeSize -= bytes; block->fFreePtr = ptr + bytes; SkDEBUGCODE(this->validate();) + SkASSERT(SkIsAlign8((size_t)ptr)); return ptr; } diff --git a/tests/MemsetTest.cpp b/tests/MemsetTest.cpp index e1f844e05c..fb5a337738 100644 --- a/tests/MemsetTest.cpp +++ b/tests/MemsetTest.cpp @@ -6,6 +6,7 @@ */ #include "SkChunkAlloc.h" +#include "SkRandom.h" #include "SkUtils.h" #include "Test.h" @@ -23,6 +24,14 @@ static void* simple_alloc(skiatest::Reporter* reporter, SkChunkAlloc* alloc, siz return ptr; } +static void check_alloc_alignment(skiatest::Reporter* reporter, + SkChunkAlloc* alloc, size_t size) { + const size_t kAlignment = 8; + void* ptr = alloc->allocThrow(size); + REPORTER_ASSERT(reporter, ptr != nullptr); + REPORTER_ASSERT(reporter, (size_t)ptr % kAlignment == 0); +} + static void test_chunkalloc(skiatest::Reporter* reporter) { static const size_t kMin = 1024; SkChunkAlloc alloc(kMin); @@ -76,6 +85,14 @@ static void test_chunkalloc(skiatest::Reporter* reporter) { REPORTER_ASSERT(reporter, freed == kMin); check_alloc(reporter, alloc, 2*kMin, size, 2); REPORTER_ASSERT(reporter, !alloc.contains(ptr)); + + //------------------------------------------------------------------------ + // test the alignment + alloc.reset(); + SkRandom rand; + for (int i = 0; i < 1000; i++) { + check_alloc_alignment(reporter, &alloc, rand.nextU16()); + } } /////////////////////////////////////////////////////////////////////////////// |