[core] Allow SkArenaAlloc to query malloc() for usable size
When allocating memory with malloc(), allocators can provide a larger size than requested. SkArenaAlloc tries to guess what jemalloc would return, and align its allocation requests on the to-be-provided size. Some platforms (e.g. glibc or bionic with malloc_usable_size(), macOS with malloc_size()) can provide the actual value. This CL adds support to skia's malloc() wrappers to get this data, and to SkArenaAlloc to use it. Note that as is, this is a no-op in skia proper. Indeed, clients can (and do, for instance Chromium does) override sk_malloc() (and friends), so Skia cannot assume that sk_malloc() memory comes from malloc(). To implement this, a client needs to override sk_malloc_usable_size() to return the actual value. Bug: chromium:1335342 Change-Id: Id8ea177e9adccc9c4446fe379b6f05e726ea07ce Reviewed-on: https://skia-review.googlesource.com/c/skia/+/549516 Commit-Queue: Herb Derby <herb@google.com> Reviewed-by: Herb Derby <herb@google.com>
This commit is contained in:
parent
955b73beec
commit
916351bd6e
@ -78,6 +78,10 @@ SK_API extern void* sk_calloc_throw(size_t count, size_t elemSize);
|
|||||||
SK_API extern void* sk_malloc_throw(size_t count, size_t elemSize);
|
SK_API extern void* sk_malloc_throw(size_t count, size_t elemSize);
|
||||||
SK_API extern void* sk_realloc_throw(void* buffer, size_t count, size_t elemSize);
|
SK_API extern void* sk_realloc_throw(void* buffer, size_t count, size_t elemSize);
|
||||||
|
|
||||||
|
// Returns the true usable size provided by the underlying allocator, or 0 if
|
||||||
|
// querying the allocation size is not supported.
|
||||||
|
SK_API extern size_t sk_malloc_usable_size(void* buffer);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These variants return nullptr on failure
|
* These variants return nullptr on failure
|
||||||
*/
|
*/
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
* found in the LICENSE file.
|
* found in the LICENSE file.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "include/private/SkMalloc.h"
|
||||||
#include "src/core/SkArenaAlloc.h"
|
#include "src/core/SkArenaAlloc.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -93,6 +94,13 @@ void SkArenaAlloc::ensureSpace(uint32_t size, uint32_t alignment) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
char* newBlock = static_cast<char*>(sk_malloc_throw(allocationSize, 1));
|
char* newBlock = static_cast<char*>(sk_malloc_throw(allocationSize, 1));
|
||||||
|
size_t actualAllocatedSize = sk_malloc_usable_size(newBlock);
|
||||||
|
// 0 means that the allocated size is not available, don't change anything
|
||||||
|
// then.
|
||||||
|
if (actualAllocatedSize) {
|
||||||
|
AssertRelease(actualAllocatedSize >= allocationSize);
|
||||||
|
allocationSize = actualAllocatedSize;
|
||||||
|
}
|
||||||
|
|
||||||
auto previousDtor = fDtorCursor;
|
auto previousDtor = fDtorCursor;
|
||||||
fCursor = newBlock;
|
fCursor = newBlock;
|
||||||
|
@ -20,3 +20,11 @@ void* sk_realloc_throw(void* buffer, size_t count, size_t elemSize) {
|
|||||||
void* sk_malloc_canfail(size_t count, size_t elemSize) {
|
void* sk_malloc_canfail(size_t count, size_t elemSize) {
|
||||||
return sk_malloc_canfail(SkSafeMath::Mul(count, elemSize));
|
return sk_malloc_canfail(SkSafeMath::Mul(count, elemSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t sk_malloc_usable_size(void* buffer) {
|
||||||
|
// Since sk_malloc() can be overridden by clients, there is no guarantee
|
||||||
|
// that the memory allocated with it comes from malloc(). So the default
|
||||||
|
// implementation can only return 0 to signal that generic support is not
|
||||||
|
// possible.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user