aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/private/SkMalloc.h90
-rw-r--r--include/private/SkTArray.h6
-rw-r--r--include/private/SkTemplates.h21
-rw-r--r--public.bzl1
-rw-r--r--src/codec/SkBmpBaseCodec.cpp2
-rw-r--r--src/codec/SkIcoCodec.cpp5
-rw-r--r--src/core/SkAutoMalloc.h2
-rw-r--r--src/core/SkAutoPixmapStorage.cpp2
-rw-r--r--src/core/SkBitmapCache.cpp2
-rw-r--r--src/core/SkMallocPixelRef.cpp31
-rw-r--r--src/core/SkRegion_path.cpp7
-rw-r--r--src/gpu/GrBuffer.cpp2
-rw-r--r--src/lazy/SkDiscardableMemoryPool.cpp2
-rw-r--r--src/ports/SkMemory_malloc.cpp22
-rw-r--r--src/ports/SkMemory_mozalloc.cpp20
15 files changed, 146 insertions, 69 deletions
diff --git a/include/private/SkMalloc.h b/include/private/SkMalloc.h
index ba14d465c1..53c3d99a8f 100644
--- a/include/private/SkMalloc.h
+++ b/include/private/SkMalloc.h
@@ -17,26 +17,52 @@
memory wrappers to be implemented by the porting layer (platform)
*/
+
+/** Free memory returned by sk_malloc(). It is safe to pass null. */
+SK_API extern void sk_free(void*);
+
+/**
+ * Called internally if we run out of memory. The platform implementation must
+ * not return, but should either throw an exception or otherwise exit.
+ */
+SK_API extern void sk_out_of_memory(void);
+
enum {
- SK_MALLOC_TEMP = 0x01, //!< hint to sk_malloc that the requested memory will be freed in the scope of the stack frame
- SK_MALLOC_THROW = 0x02 //!< instructs sk_malloc to not return normally if the memory cannot be allocated.
+#ifdef SK_SUPPORT_LEGACY_MALLOC_PORTING_LAYER
+ SK_MALLOC_TEMP = 1,
+#else
+ /**
+ * If this bit is set, the returned buffer must be zero-initialized. If this bit is not set
+ * the buffer can be uninitialized.
+ */
+ SK_MALLOC_ZERO_INITIALIZE = 1 << 0,
+#endif
+
+ /**
+ * If this bit is set, the implementation must throw/crash/quit if the request cannot
+ * be fulfilled. If this bit is not set, then it should return nullptr on failure.
+ */
+ SK_MALLOC_THROW = 1 << 1,
};
-/** Return a block of memory (at least 4-byte aligned) of at least the
- specified size. If the requested memory cannot be returned, either
- return null (if SK_MALLOC_TEMP bit is clear) or throw an exception
- (if SK_MALLOC_TEMP bit is set). To free the memory, call sk_free().
-*/
+/**
+ * Return a block of memory (at least 4-byte aligned) of at least the specified size.
+ * If the requested memory cannot be returned, either return nullptr or throw/exit, depending
+ * on the SK_MALLOC_THROW bit. If the allocation succeeds, the memory will be zero-initialized
+ * if the SK_MALLOC_ZERO_INITIALIZE bit was set.
+ *
+ * To free the memory, call sk_free()
+ */
SK_API extern void* sk_malloc_flags(size_t size, unsigned flags);
-/** Same as sk_malloc(), but hard coded to pass SK_MALLOC_THROW as the flag
-*/
-SK_API extern void* sk_malloc_throw(size_t size);
+
/** Same as standard realloc(), but this one never returns null on failure. It will throw
- an exception if it fails.
-*/
+ * an exception if it fails.
+ */
SK_API extern void* sk_realloc_throw(void* buffer, size_t size);
-/** Free memory returned by sk_malloc(). It is safe to pass null.
-*/
-SK_API extern void sk_free(void*);
+
+#ifdef SK_SUPPORT_LEGACY_MALLOC_PORTING_LAYER
+
+/** Same as sk_malloc_flags(), but hard coded to pass SK_MALLOC_THROW as the flag */
+SK_API extern void* sk_malloc_throw(size_t size);
/** Much like calloc: returns a pointer to at least size zero bytes, or NULL on failure.
*/
@@ -46,10 +72,36 @@ SK_API extern void* sk_calloc(size_t size);
*/
SK_API extern void* sk_calloc_throw(size_t size);
-/** Called internally if we run out of memory. The platform implementation must
- not return, but should either throw an exception or otherwise exit.
-*/
-SK_API extern void sk_out_of_memory(void);
+#else
+static inline void* sk_malloc_throw(size_t size) {
+ return sk_malloc_flags(size, SK_MALLOC_THROW);
+}
+
+static inline void* sk_calloc_throw(size_t size) {
+ return sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_ZERO_INITIALIZE);
+}
+#endif
+
+static inline void* sk_calloc_canfail(size_t size) {
+#ifdef SK_SUPPORT_LEGACY_MALLOC_PORTING_LAYER
+ return sk_calloc(size);
+#else
+ return sk_malloc_flags(size, SK_MALLOC_ZERO_INITIALIZE);
+#endif
+}
+
+// Performs a safe multiply count * elemSize, checking for overflow
+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_realloc_throw(void* buffer, size_t count, size_t elemSize);
+
+/**
+ * These variants return nullptr on failure
+ */
+static inline void* sk_malloc_canfail(size_t size) {
+ return sk_malloc_flags(size, 0);
+}
+SK_API extern void* sk_malloc_canfail(size_t count, size_t elemSize);
// bzero is safer than memset, but we can't rely on it, so... sk_bzero()
static inline void sk_bzero(void* buffer, size_t size) {
diff --git a/include/private/SkTArray.h b/include/private/SkTArray.h
index 3f4cc429b4..68dab9a33a 100644
--- a/include/private/SkTArray.h
+++ b/include/private/SkTArray.h
@@ -445,7 +445,7 @@ private:
fReserved = false;
} else {
fAllocCount = SkTMax(count, SkTMax(kMinHeapAllocCount, reserveCount));
- fMemArray = sk_malloc_throw(fAllocCount * sizeof(T));
+ fMemArray = sk_malloc_throw(fAllocCount, sizeof(T));
fOwnMemory = true;
fReserved = reserveCount > 0;
}
@@ -460,7 +460,7 @@ private:
fReserved = false;
if (count > preallocCount) {
fAllocCount = SkTMax(count, kMinHeapAllocCount);
- fMemArray = sk_malloc_throw(fAllocCount * sizeof(T));
+ fMemArray = sk_malloc_throw(fAllocCount, sizeof(T));
fOwnMemory = true;
} else {
fAllocCount = preallocCount;
@@ -537,7 +537,7 @@ private:
return;
}
fAllocCount = newAllocCount;
- void* newMemArray = sk_malloc_throw(fAllocCount * sizeof(T));
+ void* newMemArray = sk_malloc_throw(fAllocCount, sizeof(T));
this->move(newMemArray);
if (fOwnMemory) {
sk_free(fMemArray);
diff --git a/include/private/SkTemplates.h b/include/private/SkTemplates.h
index 8a605fbd02..3f70203555 100644
--- a/include/private/SkTemplates.h
+++ b/include/private/SkTemplates.h
@@ -175,12 +175,7 @@ public:
}
if (count > kCount) {
- const uint64_t size64 = sk_64_mul(count, sizeof(T));
- const size_t size = static_cast<size_t>(size64);
- if (size != size64) {
- sk_out_of_memory();
- }
- fArray = (T*) sk_malloc_throw(size);
+ fArray = (T*) sk_malloc_throw(count, sizeof(T));
} else if (count > 0) {
fArray = (T*) fStorage;
} else {
@@ -250,7 +245,7 @@ public:
/** Allocates space for 'count' Ts. */
explicit SkAutoTMalloc(size_t count) {
- fPtr = count ? (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW) : nullptr;
+ fPtr = count ? (T*)sk_malloc_throw(count, sizeof(T)) : nullptr;
}
SkAutoTMalloc(SkAutoTMalloc<T>&& that) : fPtr(that.release()) {}
@@ -271,7 +266,7 @@ public:
/** Resize the memory area pointed to by the current ptr without preserving contents. */
T* reset(size_t count = 0) {
sk_free(fPtr);
- fPtr = count ? (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW) : nullptr;
+ fPtr = count ? (T*)sk_malloc_throw(count, sizeof(T)) : nullptr;
return fPtr;
}
@@ -322,7 +317,7 @@ public:
SkAutoSTMalloc(size_t count) {
if (count > kCount) {
- fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
+ fPtr = (T*)sk_malloc_throw(count, sizeof(T));
} else if (count) {
fPtr = fTStorage;
} else {
@@ -342,7 +337,7 @@ public:
sk_free(fPtr);
}
if (count > kCount) {
- fPtr = (T*)sk_malloc_throw(count * sizeof(T));
+ fPtr = (T*)sk_malloc_throw(count, sizeof(T));
} else if (count) {
fPtr = fTStorage;
} else {
@@ -373,14 +368,14 @@ public:
void realloc(size_t count) {
if (count > kCount) {
if (fPtr == fTStorage) {
- fPtr = (T*)sk_malloc_throw(count * sizeof(T));
+ fPtr = (T*)sk_malloc_throw(count, sizeof(T));
memcpy(fPtr, fTStorage, kCount * sizeof(T));
} else {
- fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T));
+ fPtr = (T*)sk_realloc_throw(fPtr, count, sizeof(T));
}
} else if (count) {
if (fPtr != fTStorage) {
- fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T));
+ fPtr = (T*)sk_realloc_throw(fPtr, count, sizeof(T));
}
} else {
this->reset(0);
diff --git a/public.bzl b/public.bzl
index 1e2894058a..d856db20b0 100644
--- a/public.bzl
+++ b/public.bzl
@@ -586,6 +586,7 @@ def base_defines(os_conditions):
"SK_JUMPER_DISABLE_8BIT",
# JPEG is in codec_limited
"SK_HAS_JPEG_LIBRARY",
+ "SK_SUPPORT_LEGACY_MALLOC_PORTING_LAYER",
] + skia_select(
os_conditions,
[
diff --git a/src/codec/SkBmpBaseCodec.cpp b/src/codec/SkBmpBaseCodec.cpp
index 1071ff38e7..c548514057 100644
--- a/src/codec/SkBmpBaseCodec.cpp
+++ b/src/codec/SkBmpBaseCodec.cpp
@@ -13,5 +13,5 @@ SkBmpBaseCodec::SkBmpBaseCodec(int width, int height, const SkEncodedInfo& info,
std::unique_ptr<SkStream> stream,
uint16_t bitsPerPixel, SkCodec::SkScanlineOrder rowOrder)
: INHERITED(width, height, info, std::move(stream), bitsPerPixel, rowOrder)
- , fSrcBuffer(sk_malloc_flags(this->srcRowBytes(), 0))
+ , fSrcBuffer(sk_malloc_canfail(this->srcRowBytes()))
{}
diff --git a/src/codec/SkIcoCodec.cpp b/src/codec/SkIcoCodec.cpp
index 1b9321c3ea..af9125565a 100644
--- a/src/codec/SkIcoCodec.cpp
+++ b/src/codec/SkIcoCodec.cpp
@@ -55,8 +55,7 @@ std::unique_ptr<SkCodec> SkIcoCodec::MakeFromStream(std::unique_ptr<SkStream> st
uint32_t offset;
uint32_t size;
};
- SkAutoFree dirEntryBuffer(sk_malloc_flags(sizeof(Entry) * numImages,
- SK_MALLOC_TEMP));
+ SkAutoFree dirEntryBuffer(sk_malloc_canfail(sizeof(Entry) * numImages));
if (!dirEntryBuffer) {
SkCodecPrintf("Error: OOM allocating ICO directory for %i images.\n",
numImages);
@@ -131,7 +130,7 @@ std::unique_ptr<SkCodec> SkIcoCodec::MakeFromStream(std::unique_ptr<SkStream> st
bytesRead = offset;
// Create a new stream for the embedded codec
- SkAutoFree buffer(sk_malloc_flags(size, 0));
+ SkAutoFree buffer(sk_malloc_canfail(size));
if (!buffer) {
SkCodecPrintf("Warning: OOM trying to create embedded stream.\n");
break;
diff --git a/src/core/SkAutoMalloc.h b/src/core/SkAutoMalloc.h
index 03cbf79ea6..f5c872954d 100644
--- a/src/core/SkAutoMalloc.h
+++ b/src/core/SkAutoMalloc.h
@@ -144,7 +144,7 @@ public:
SkASSERT(fPtr != fStorage); // otherwise we lied when setting didChangeAlloc.
fPtr = fStorage;
} else {
- fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP);
+ fPtr = sk_malloc_throw(size);
}
fSize = size;
diff --git a/src/core/SkAutoPixmapStorage.cpp b/src/core/SkAutoPixmapStorage.cpp
index 47f41e7b92..72194233a8 100644
--- a/src/core/SkAutoPixmapStorage.cpp
+++ b/src/core/SkAutoPixmapStorage.cpp
@@ -40,7 +40,7 @@ bool SkAutoPixmapStorage::tryAlloc(const SkImageInfo& info) {
if (SkImageInfo::ByteSizeOverflowed(size)) {
return false;
}
- void* pixels = sk_malloc_flags(size, 0);
+ void* pixels = sk_malloc_canfail(size);
if (nullptr == pixels) {
return false;
}
diff --git a/src/core/SkBitmapCache.cpp b/src/core/SkBitmapCache.cpp
index 210787e47d..cb88070ba4 100644
--- a/src/core/SkBitmapCache.cpp
+++ b/src/core/SkBitmapCache.cpp
@@ -301,7 +301,7 @@ SkBitmapCache::RecPtr SkBitmapCache::Alloc(const SkBitmapCacheDesc& desc, const
if (factory) {
dm.reset(factory(size));
} else {
- block = sk_malloc_flags(size, 0);
+ block = sk_malloc_canfail(size);
}
if (!dm && !block) {
return nullptr;
diff --git a/src/core/SkMallocPixelRef.cpp b/src/core/SkMallocPixelRef.cpp
index 6e402c98f7..2933e48cc4 100644
--- a/src/core/SkMallocPixelRef.cpp
+++ b/src/core/SkMallocPixelRef.cpp
@@ -8,8 +8,27 @@
#include "SkMallocPixelRef.h"
#include "SkBitmap.h"
#include "SkReadBuffer.h"
+#include "SkSafeMath.h"
#include "SkWriteBuffer.h"
+void* sk_calloc_throw(size_t count, size_t elemSize) {
+ return sk_calloc_throw(SkSafeMath::Mul(count, elemSize));
+}
+
+void* sk_malloc_throw(size_t count, size_t elemSize) {
+ return sk_malloc_throw(SkSafeMath::Mul(count, elemSize));
+}
+
+void* sk_realloc_throw(void* buffer, size_t count, size_t elemSize) {
+ return sk_realloc_throw(buffer, SkSafeMath::Mul(count, elemSize));
+}
+
+void* sk_malloc_canfail(size_t count, size_t elemSize) {
+ return sk_malloc_canfail(SkSafeMath::Mul(count, elemSize));
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
// assumes ptr was allocated via sk_malloc
static void sk_free_releaseproc(void* ptr, void*) {
sk_free(ptr);
@@ -63,15 +82,13 @@ sk_sp<SkPixelRef> SkMallocPixelRef::MakeUsing(void*(*allocProc)(size_t),
sk_free_releaseproc, nullptr));
}
-sk_sp<SkPixelRef> SkMallocPixelRef::MakeAllocate(const SkImageInfo& info,
- size_t rowBytes) {
- auto sk_malloc_nothrow = [](size_t size) { return sk_malloc_flags(size, 0); };
- return MakeUsing(sk_malloc_nothrow, info, rowBytes);
+sk_sp<SkPixelRef> SkMallocPixelRef::MakeAllocate(const SkImageInfo& info, size_t rowBytes) {
+ return MakeUsing(sk_malloc_canfail, info, rowBytes);
}
sk_sp<SkPixelRef> SkMallocPixelRef::MakeZeroed(const SkImageInfo& info,
size_t rowBytes) {
- return MakeUsing(sk_calloc, info, rowBytes);
+ return MakeUsing(sk_calloc_canfail, info, rowBytes);
}
static void sk_data_releaseproc(void*, void* dataPtr) {
@@ -93,8 +110,8 @@ sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithProc(const SkImageInfo& info,
}
sk_sp<SkPixelRef> SkMallocPixelRef::MakeWithData(const SkImageInfo& info,
- size_t rowBytes,
- sk_sp<SkData> data) {
+ size_t rowBytes,
+ sk_sp<SkData> data) {
SkASSERT(data != nullptr);
if (!is_valid(info)) {
return nullptr;
diff --git a/src/core/SkRegion_path.cpp b/src/core/SkRegion_path.cpp
index fec78256b3..e6af059c8e 100644
--- a/src/core/SkRegion_path.cpp
+++ b/src/core/SkRegion_path.cpp
@@ -144,12 +144,7 @@ bool SkRgnBuilder::init(int maxHeight, int maxTransitions, bool pathIsInverse) {
}
fStorageCount = sk_64_asS32(count);
- int64_t size = sk_64_mul(fStorageCount, sizeof(SkRegion::RunType));
- if (size < 0 || !sk_64_isS32(size)) {
- return false;
- }
-
- fStorage = (SkRegion::RunType*)sk_malloc_flags(sk_64_asS32(size), 0);
+ fStorage = (SkRegion::RunType*)sk_malloc_canfail(fStorageCount, sizeof(SkRegion::RunType));
if (nullptr == fStorage) {
return false;
}
diff --git a/src/gpu/GrBuffer.cpp b/src/gpu/GrBuffer.cpp
index c92b2968b9..cd7862a226 100644
--- a/src/gpu/GrBuffer.cpp
+++ b/src/gpu/GrBuffer.cpp
@@ -16,7 +16,7 @@ GrBuffer* GrBuffer::CreateCPUBacked(GrGpu* gpu, size_t sizeInBytes, GrBufferType
if (gpu->caps()->mustClearUploadedBufferData()) {
cpuData = sk_calloc_throw(sizeInBytes);
} else {
- cpuData = sk_malloc_flags(sizeInBytes, SK_MALLOC_THROW);
+ cpuData = sk_malloc_throw(sizeInBytes);
}
if (data) {
memcpy(cpuData, data, sizeInBytes);
diff --git a/src/lazy/SkDiscardableMemoryPool.cpp b/src/lazy/SkDiscardableMemoryPool.cpp
index 6e5582a494..394e325707 100644
--- a/src/lazy/SkDiscardableMemoryPool.cpp
+++ b/src/lazy/SkDiscardableMemoryPool.cpp
@@ -164,7 +164,7 @@ void DiscardableMemoryPool::dumpDownTo(size_t budget) {
}
std::unique_ptr<SkDiscardableMemory> DiscardableMemoryPool::make(size_t bytes) {
- SkAutoFree addr(sk_malloc_flags(bytes, 0));
+ SkAutoFree addr(sk_malloc_canfail(bytes));
if (nullptr == addr) {
return nullptr;
}
diff --git a/src/ports/SkMemory_malloc.cpp b/src/ports/SkMemory_malloc.cpp
index 05c69d53ae..aa1cfacb47 100644
--- a/src/ports/SkMemory_malloc.cpp
+++ b/src/ports/SkMemory_malloc.cpp
@@ -54,10 +54,6 @@ void sk_out_of_memory(void) {
#endif
}
-void* sk_malloc_throw(size_t size) {
- return sk_malloc_flags(size, SK_MALLOC_THROW);
-}
-
void* sk_realloc_throw(void* addr, size_t size) {
return throw_on_failure(size, realloc(addr, size));
}
@@ -69,7 +65,16 @@ void sk_free(void* p) {
}
void* sk_malloc_flags(size_t size, unsigned flags) {
- void* p = malloc(size);
+ void* p;
+#ifdef SK_SUPPORT_LEGACY_MALLOC_PORTING_LAYER
+ p = malloc(size);
+#else
+ if (flags & SK_MALLOC_ZERO_INITIALIZE) {
+ p = calloc(size, 1);
+ } else {
+ p = malloc(size);
+ }
+#endif
if (flags & SK_MALLOC_THROW) {
return throw_on_failure(size, p);
} else {
@@ -77,10 +82,15 @@ void* sk_malloc_flags(size_t size, unsigned flags) {
}
}
+#ifdef SK_SUPPORT_LEGACY_MALLOC_PORTING_LAYER
+void* sk_malloc_throw(size_t size) {
+ return sk_malloc_flags(size, SK_MALLOC_THROW);
+}
void* sk_calloc(size_t size) {
return calloc(size, 1);
}
-
void* sk_calloc_throw(size_t size) {
return throw_on_failure(size, sk_calloc(size));
}
+#endif
+
diff --git a/src/ports/SkMemory_mozalloc.cpp b/src/ports/SkMemory_mozalloc.cpp
index bf5971ba07..e13b94612a 100644
--- a/src/ports/SkMemory_mozalloc.cpp
+++ b/src/ports/SkMemory_mozalloc.cpp
@@ -22,22 +22,28 @@ void sk_out_of_memory(void) {
mozalloc_handle_oom(0);
}
-void* sk_malloc_throw(size_t size) {
- return sk_malloc_flags(size, SK_MALLOC_THROW);
+void sk_free(void* p) {
+ free(p);
}
void* sk_realloc_throw(void* addr, size_t size) {
return moz_xrealloc(addr, size);
}
-void sk_free(void* p) {
- free(p);
-}
-
void* sk_malloc_flags(size_t size, unsigned flags) {
+#ifndef SK_SUPPORT_LEGACY_MALLOC_PORTING_LAYER
+ if (flags & SK_MALLOC_ZERO_INITIALIZE) {
+ return (flags & SK_MALLOC_THROW) ? moz_xcalloc(size, 1) : calloc(size, 1);
+ }
+#endif
return (flags & SK_MALLOC_THROW) ? moz_xmalloc(size) : malloc(size);
}
+#ifdef SK_SUPPORT_LEGACY_MALLOC_PORTING_LAYER
+void* sk_malloc_throw(size_t size) {
+ return sk_malloc_flags(size, SK_MALLOC_THROW);
+}
+
void* sk_calloc(size_t size) {
return calloc(size, 1);
}
@@ -45,3 +51,5 @@ void* sk_calloc(size_t size) {
void* sk_calloc_throw(size_t size) {
return moz_xcalloc(size, 1);
}
+#endif
+