Bug 1224396 - Skia path allocation cleanups. r=msreckovic

MozReview-Commit-ID: GAf2vC1Fucv
This commit is contained in:
Lee Salzman 2017-11-22 12:19:29 -05:00
parent ed9b200c0d
commit 894f5cc99e
3 changed files with 36 additions and 16 deletions

View File

@ -16,7 +16,7 @@
#include "SkRRect.h"
#include "SkRect.h"
#include "SkRefCnt.h"
#include <stddef.h> // ptrdiff_t
#include "../private/SkTemplates.h"
class SkRBuffer;
class SkWBuffer;
@ -433,31 +433,35 @@ private:
*/
void makeSpace(size_t size) {
SkDEBUGCODE(this->validate();)
ptrdiff_t growSize = size - fFreeSpace;
if (growSize <= 0) {
if (size <= fFreeSpace) {
return;
}
size_t growSize = size - fFreeSpace;
size_t oldSize = this->currSize();
// round to next multiple of 8 bytes
growSize = (growSize + 7) & ~static_cast<size_t>(7);
// we always at least double the allocation
if (static_cast<size_t>(growSize) < oldSize) {
if (growSize < oldSize) {
growSize = oldSize;
}
if (growSize < kMinSize) {
growSize = kMinSize;
}
size_t newSize = oldSize + growSize;
constexpr size_t maxSize = std::numeric_limits<size_t>::max();
size_t newSize;
if (growSize <= maxSize - oldSize) {
newSize = oldSize + growSize;
} else {
SK_ABORT("Path too big.");
}
// Note that realloc could memcpy more than we need. It seems to be a win anyway. TODO:
// encapsulate this.
fPoints = reinterpret_cast<SkPoint*>(sk_realloc_throw(fPoints, newSize));
size_t oldVerbSize = fVerbCnt * sizeof(uint8_t);
void* newVerbsDst = reinterpret_cast<void*>(
reinterpret_cast<intptr_t>(fPoints) + newSize - oldVerbSize);
void* oldVerbsSrc = reinterpret_cast<void*>(
reinterpret_cast<intptr_t>(fPoints) + oldSize - oldVerbSize);
void* newVerbsDst = SkTAddOffset<void>(fPoints, newSize - oldVerbSize);
void* oldVerbsSrc = SkTAddOffset<void>(fPoints, oldSize - oldVerbSize);
memmove(newVerbsDst, oldVerbsSrc, oldVerbSize);
fVerbs = reinterpret_cast<uint8_t*>(reinterpret_cast<intptr_t>(fPoints) + newSize);
fVerbs = SkTAddOffset<uint8_t>(fPoints, newSize);
fFreeSpace += growSize;
SkDEBUGCODE(this->validate();)
}

View File

@ -8,6 +8,7 @@
#include <algorithm>
#include <cstddef>
#include "SkArenaAlloc.h"
#include "SkTypes.h"
static char* end_chain(char*) { return nullptr; }
@ -95,19 +96,31 @@ void SkArenaAlloc::ensureSpace(uint32_t size, uint32_t alignment) {
// This must be conservative to add the right amount of extra memory to handle the alignment
// padding.
constexpr uint32_t alignof_max_align_t = 8;
uint32_t objSizeAndOverhead = size + headerSize + sizeof(Footer);
constexpr uint32_t maxSize = std::numeric_limits<uint32_t>::max();
constexpr uint32_t overhead = headerSize + sizeof(Footer);
SkASSERT_RELEASE(size <= maxSize - overhead);
uint32_t objSizeAndOverhead = size + overhead;
if (alignment > alignof_max_align_t) {
objSizeAndOverhead += alignment - 1;
uint32_t alignmentOverhead = alignment - 1;
SkASSERT_RELEASE(objSizeAndOverhead <= maxSize - alignmentOverhead);
objSizeAndOverhead += alignmentOverhead;
}
uint32_t allocationSize = std::max(objSizeAndOverhead, fExtraSize * fFib0);
fFib0 += fFib1;
std::swap(fFib0, fFib1);
uint32_t minAllocationSize;
if (fExtraSize <= maxSize / fFib0) {
minAllocationSize = fExtraSize * fFib0;
fFib0 += fFib1;
std::swap(fFib0, fFib1);
} else {
minAllocationSize = maxSize;
}
uint32_t allocationSize = std::max(objSizeAndOverhead, minAllocationSize);
// Round up to a nice size. If > 32K align to 4K boundary else up to max_align_t. The > 32K
// heuristic is from the JEMalloc behavior.
{
uint32_t mask = allocationSize > (1 << 15) ? (1 << 12) - 1 : 16 - 1;
SkASSERT_RELEASE(allocationSize <= maxSize - mask);
allocationSize = (allocationSize + mask) & ~mask;
}

View File

@ -157,6 +157,7 @@ private:
template <typename T>
char* commonArrayAlloc(uint32_t count) {
char* objStart;
SkASSERT_RELEASE(count <= std::numeric_limits<uint32_t>::max() / sizeof(T));
uint32_t arraySize = SkTo<uint32_t>(count * sizeof(T));
uint32_t alignment = SkTo<uint32_t>(alignof(T));
@ -164,7 +165,9 @@ private:
objStart = this->allocObject(arraySize, alignment);
fCursor = objStart + arraySize;
} else {
uint32_t totalSize = arraySize + sizeof(Footer) + sizeof(uint32_t);
constexpr uint32_t overhead = sizeof(Footer) + sizeof(uint32_t);
SkASSERT_RELEASE(arraySize <= std::numeric_limits<uint32_t>::max() - overhead);
uint32_t totalSize = arraySize + overhead;
objStart = this->allocObjectWithFooter(totalSize, alignment);
// Can never be UB because max value is alignof(T).