- Revision
- 208690
- Author
- mark....@apple.com
- Date
- 2016-11-14 10:04:06 -0800 (Mon, 14 Nov 2016)
Log Message
Add debugging facility to limit the max single allocation size.
https://bugs.webkit.org/show_bug.cgi?id=164681
Reviewed by Keith Miller.
Source/_javascript_Core:
Added JSC option to set FastMalloc's maxSingleAllocationSize for testing purposes.
This option is only available on Debug builds.
* runtime/Options.cpp:
(JSC::Options::isAvailable):
(JSC::recomputeDependentOptions):
* runtime/Options.h:
Source/WTF:
This is useful for simulating memory allocation failures on resource constraint
devices for testing purposes.
This facility is only conditionally compiled in on debug builds. It does not
have any burden on release builds at all. When in use, the max single allocation
size limit applies to individual allocations. For malloc (and similar), the
allocation will crash in FastMalloc if the requested size exceeds the set max
single allocation size. For tryMalloc (and similar), the allocation returns
nullptr if the requested size exceeds the set max single allocation size. The
max single allocation size is set to std::numeric_limit<size_t>::max() by default
(i.e. when not set and no limit is in effect).
Also fixed non-bmalloc versions of fastAlignedMalloc() to crash when allocation
fails.
* wtf/FastMalloc.cpp:
(WTF::fastSetMaxSingleAllocationSize):
(WTF::fastAlignedMalloc):
(WTF::tryFastAlignedMalloc):
(WTF::tryFastMalloc):
(WTF::fastMalloc):
(WTF::tryFastCalloc):
(WTF::fastCalloc):
(WTF::fastRealloc):
* wtf/FastMalloc.h:
Modified Paths
Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (208689 => 208690)
--- trunk/Source/_javascript_Core/ChangeLog 2016-11-14 17:59:08 UTC (rev 208689)
+++ trunk/Source/_javascript_Core/ChangeLog 2016-11-14 18:04:06 UTC (rev 208690)
@@ -1,3 +1,18 @@
+2016-11-13 Mark Lam <mark....@apple.com>
+
+ Add debugging facility to limit the max single allocation size.
+ https://bugs.webkit.org/show_bug.cgi?id=164681
+
+ Reviewed by Keith Miller.
+
+ Added JSC option to set FastMalloc's maxSingleAllocationSize for testing purposes.
+ This option is only available on Debug builds.
+
+ * runtime/Options.cpp:
+ (JSC::Options::isAvailable):
+ (JSC::recomputeDependentOptions):
+ * runtime/Options.h:
+
2016-11-12 Joseph Pecoraro <pecor...@apple.com>
Follow-up fix to r208639.
Modified: trunk/Source/_javascript_Core/runtime/Options.cpp (208689 => 208690)
--- trunk/Source/_javascript_Core/runtime/Options.cpp 2016-11-14 17:59:08 UTC (rev 208689)
+++ trunk/Source/_javascript_Core/runtime/Options.cpp 2016-11-14 18:04:06 UTC (rev 208690)
@@ -136,6 +136,10 @@
if (id == reportLLIntStatsID || id == llintStatsFileID)
return true;
#endif
+#if !defined(NDEBUG)
+ if (id == maxSingleAllocationSizeID)
+ return true;
+#endif
return false;
}
@@ -396,6 +400,12 @@
#if ENABLE(LLINT_STATS)
LLInt::Data::loadStats();
#endif
+#if !defined(NDEBUG)
+ if (Options::maxSingleAllocationSize())
+ fastSetMaxSingleAllocationSize(Options::maxSingleAllocationSize());
+ else
+ fastSetMaxSingleAllocationSize(std::numeric_limits<size_t>::max());
+#endif
}
void Options::initialize()
Modified: trunk/Source/_javascript_Core/runtime/Options.h (208689 => 208690)
--- trunk/Source/_javascript_Core/runtime/Options.h 2016-11-14 17:59:08 UTC (rev 208689)
+++ trunk/Source/_javascript_Core/runtime/Options.h 2016-11-14 18:04:06 UTC (rev 208690)
@@ -323,6 +323,7 @@
v(bool, useZombieMode, false, Normal, "debugging option to scribble over dead objects with 0xdeadbeef") \
v(bool, useImmortalObjects, false, Normal, "debugging option to keep all objects alive forever") \
v(bool, dumpObjectStatistics, false, Normal, nullptr) \
+ v(unsigned, maxSingleAllocationSize, 0, Configurable, "debugging option to limit individual allocations to a max size (0 = limit not set, N = limit size in bytes)") \
\
v(gcLogLevel, logGC, GCLogging::None, Normal, "debugging option to log GC activity (0 = None, 1 = Basic, 2 = Verbose)") \
v(bool, useGC, true, Normal, nullptr) \
Modified: trunk/Source/WTF/ChangeLog (208689 => 208690)
--- trunk/Source/WTF/ChangeLog 2016-11-14 17:59:08 UTC (rev 208689)
+++ trunk/Source/WTF/ChangeLog 2016-11-14 18:04:06 UTC (rev 208690)
@@ -1,3 +1,36 @@
+2016-11-13 Mark Lam <mark....@apple.com>
+
+ Add debugging facility to limit the max single allocation size.
+ https://bugs.webkit.org/show_bug.cgi?id=164681
+
+ Reviewed by Keith Miller.
+
+ This is useful for simulating memory allocation failures on resource constraint
+ devices for testing purposes.
+
+ This facility is only conditionally compiled in on debug builds. It does not
+ have any burden on release builds at all. When in use, the max single allocation
+ size limit applies to individual allocations. For malloc (and similar), the
+ allocation will crash in FastMalloc if the requested size exceeds the set max
+ single allocation size. For tryMalloc (and similar), the allocation returns
+ nullptr if the requested size exceeds the set max single allocation size. The
+ max single allocation size is set to std::numeric_limit<size_t>::max() by default
+ (i.e. when not set and no limit is in effect).
+
+ Also fixed non-bmalloc versions of fastAlignedMalloc() to crash when allocation
+ fails.
+
+ * wtf/FastMalloc.cpp:
+ (WTF::fastSetMaxSingleAllocationSize):
+ (WTF::fastAlignedMalloc):
+ (WTF::tryFastAlignedMalloc):
+ (WTF::tryFastMalloc):
+ (WTF::fastMalloc):
+ (WTF::tryFastCalloc):
+ (WTF::fastCalloc):
+ (WTF::fastRealloc):
+ * wtf/FastMalloc.h:
+
2016-11-13 JF Bastien <jfbast...@apple.com>
Implement WTF::Expected
Modified: trunk/Source/WTF/wtf/FastMalloc.cpp (208689 => 208690)
--- trunk/Source/WTF/wtf/FastMalloc.cpp 2016-11-14 17:59:08 UTC (rev 208689)
+++ trunk/Source/WTF/wtf/FastMalloc.cpp 2016-11-14 18:04:06 UTC (rev 208690)
@@ -46,6 +46,33 @@
namespace WTF {
+#if !defined(NDEBUG)
+namespace {
+size_t maxSingleAllocationSize = std::numeric_limits<size_t>::max();
+};
+
+void fastSetMaxSingleAllocationSize(size_t size)
+{
+ maxSingleAllocationSize = size;
+}
+
+#define ASSERT_IS_WITHIN_LIMIT(size) do { \
+ size_t size__ = (size); \
+ ASSERT_WITH_MESSAGE((size__) <= maxSingleAllocationSize, "Requested size (%zu) exceeds max single allocation size set for testing (%zu)", (size__), maxSingleAllocationSize); \
+ } while (false)
+
+#define FAIL_IF_EXCEEDS_LIMIT(size) do { \
+ if (UNLIKELY((size) > maxSingleAllocationSize)) \
+ return nullptr; \
+ } while (false)
+
+#else // !defined(NDEBUG)
+
+#define ASSERT_IS_WITHIN_LIMIT(size)
+#define FAIL_IF_EXCEEDS_LIMIT(size)
+
+#endif // !defined(NDEBUG)
+
void* fastZeroedMalloc(size_t n)
{
void* result = fastMalloc(n);
@@ -98,11 +125,16 @@
void* fastAlignedMalloc(size_t alignment, size_t size)
{
- return _aligned_malloc(size, alignment);
+ ASSERT_IS_WITHIN_LIMIT(size);
+ void* p = _aligned_malloc(size, alignment);
+ if (UNLIKELY(!p))
+ CRASH();
+ return p;
}
void* tryFastAlignedMalloc(size_t alignment, size_t size)
{
+ FAIL_IF_EXCEEDS_LIMIT(size);
return _aligned_malloc(size, alignment);
}
@@ -115,13 +147,17 @@
void* fastAlignedMalloc(size_t alignment, size_t size)
{
+ ASSERT_IS_WITHIN_LIMIT(size);
void* p = nullptr;
posix_memalign(&p, alignment, size);
+ if (UNLIKELY(!p))
+ CRASH();
return p;
}
void* tryFastAlignedMalloc(size_t alignment, size_t size)
{
+ FAIL_IF_EXCEEDS_LIMIT(size);
void* p = nullptr;
posix_memalign(&p, alignment, size);
return p;
@@ -136,11 +172,13 @@
TryMallocReturnValue tryFastMalloc(size_t n)
{
+ FAIL_IF_EXCEEDS_LIMIT(n);
return malloc(n);
}
void* fastMalloc(size_t n)
{
+ ASSERT_IS_WITHIN_LIMIT(n);
void* result = malloc(n);
if (!result)
CRASH();
@@ -150,11 +188,13 @@
TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size)
{
+ FAIL_IF_EXCEEDS_LIMIT(n_elements * element_size);
return calloc(n_elements, element_size);
}
void* fastCalloc(size_t n_elements, size_t element_size)
{
+ ASSERT_IS_WITHIN_LIMIT(n_elements * element_size);
void* result = calloc(n_elements, element_size);
if (!result)
CRASH();
@@ -169,6 +209,7 @@
void* fastRealloc(void* p, size_t n)
{
+ ASSERT_IS_WITHIN_LIMIT(n);
void* result = realloc(p, n);
if (!result)
CRASH();
@@ -211,11 +252,13 @@
void* fastMalloc(size_t size)
{
+ ASSERT_IS_WITHIN_LIMIT(size);
return bmalloc::api::malloc(size);
}
void* fastCalloc(size_t numElements, size_t elementSize)
{
+ ASSERT_IS_WITHIN_LIMIT(numElements * elementSize);
Checked<size_t> checkedSize = elementSize;
checkedSize *= numElements;
void* result = fastZeroedMalloc(checkedSize.unsafeGet());
@@ -226,6 +269,7 @@
void* fastRealloc(void* object, size_t size)
{
+ ASSERT_IS_WITHIN_LIMIT(size);
return bmalloc::api::realloc(object, size);
}
@@ -249,11 +293,13 @@
void* fastAlignedMalloc(size_t alignment, size_t size)
{
+ ASSERT_IS_WITHIN_LIMIT(size);
return bmalloc::api::memalign(alignment, size);
}
void* tryFastAlignedMalloc(size_t alignment, size_t size)
{
+ FAIL_IF_EXCEEDS_LIMIT(size);
return bmalloc::api::tryMemalign(alignment, size);
}
@@ -264,11 +310,13 @@
TryMallocReturnValue tryFastMalloc(size_t size)
{
+ FAIL_IF_EXCEEDS_LIMIT(size);
return bmalloc::api::tryMalloc(size);
}
TryMallocReturnValue tryFastCalloc(size_t numElements, size_t elementSize)
{
+ FAIL_IF_EXCEEDS_LIMIT(numElements * elementSize);
Checked<size_t, RecordOverflow> checkedSize = elementSize;
checkedSize *= numElements;
if (checkedSize.hasOverflowed())
Modified: trunk/Source/WTF/wtf/FastMalloc.h (208689 => 208690)
--- trunk/Source/WTF/wtf/FastMalloc.h 2016-11-14 17:59:08 UTC (rev 208689)
+++ trunk/Source/WTF/wtf/FastMalloc.h 2016-11-14 18:04:06 UTC (rev 208690)
@@ -27,6 +27,10 @@
namespace WTF {
+#if !defined(NDEBUG)
+void fastSetMaxSingleAllocationSize(size_t);
+#endif
+
class TryMallocReturnValue {
public:
TryMallocReturnValue(void*);
@@ -102,6 +106,10 @@
} // namespace WTF
+#if !defined(NDEBUG)
+using WTF::fastSetMaxSingleAllocationSize;
+#endif
+
using WTF::isFastMallocEnabled;
using WTF::fastCalloc;
using WTF::fastFree;