aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar milko.leporis <milko.leporis@imgtec.com>2016-06-05 13:14:21 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-06-05 13:14:21 -0700
commit401e77cfe126eea1a12bd81410871fdb80739283 (patch)
tree1904f87310a09ed1eeacf50a70ba73ae9cdc812d
parent863689c3f468acdd9b9e06e0835c5fd1e2cad4c6 (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.gypi18
-rw-r--r--include/core/SkChunkAlloc.h11
-rw-r--r--src/core/SkChunkAlloc.cpp15
-rw-r--r--tests/MemsetTest.cpp17
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());
+ }
}
///////////////////////////////////////////////////////////////////////////////