Changeset 208690 in webkit


Ignore:
Timestamp:
Nov 14, 2016, 10:04:06 AM (9 years ago)
Author:
mark.lam@apple.com
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/JavaScriptCore:

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:
Location:
trunk/Source
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r208643 r208690  
     12016-11-13  Mark Lam  <mark.lam@apple.com>
     2
     3        Add debugging facility to limit the max single allocation size.
     4        https://bugs.webkit.org/show_bug.cgi?id=164681
     5
     6        Reviewed by Keith Miller.
     7
     8        Added JSC option to set FastMalloc's maxSingleAllocationSize for testing purposes.
     9        This option is only available on Debug builds.
     10
     11        * runtime/Options.cpp:
     12        (JSC::Options::isAvailable):
     13        (JSC::recomputeDependentOptions):
     14        * runtime/Options.h:
     15
    1162016-11-12  Joseph Pecoraro  <pecoraro@apple.com>
    217
  • trunk/Source/JavaScriptCore/runtime/Options.cpp

    r207491 r208690  
    137137        return true;
    138138#endif
     139#if !defined(NDEBUG)
     140    if (id == maxSingleAllocationSizeID)
     141        return true;
     142#endif
    139143    return false;
    140144}
     
    396400#if ENABLE(LLINT_STATS)
    397401    LLInt::Data::loadStats();
     402#endif
     403#if !defined(NDEBUG)
     404    if (Options::maxSingleAllocationSize())
     405        fastSetMaxSingleAllocationSize(Options::maxSingleAllocationSize());
     406    else
     407        fastSetMaxSingleAllocationSize(std::numeric_limits<size_t>::max());
    398408#endif
    399409}
  • trunk/Source/JavaScriptCore/runtime/Options.h

    r208563 r208690  
    324324    v(bool, useImmortalObjects, false, Normal, "debugging option to keep all objects alive forever") \
    325325    v(bool, dumpObjectStatistics, false, Normal, nullptr) \
     326    v(unsigned, maxSingleAllocationSize, 0, Configurable, "debugging option to limit individual allocations to a max size (0 = limit not set, N = limit size in bytes)") \
    326327    \
    327328    v(gcLogLevel, logGC, GCLogging::None, Normal, "debugging option to log GC activity (0 = None, 1 = Basic, 2 = Verbose)") \
  • trunk/Source/WTF/ChangeLog

    r208670 r208690  
     12016-11-13  Mark Lam  <mark.lam@apple.com>
     2
     3        Add debugging facility to limit the max single allocation size.
     4        https://bugs.webkit.org/show_bug.cgi?id=164681
     5
     6        Reviewed by Keith Miller.
     7
     8        This is useful for simulating memory allocation failures on resource constraint
     9        devices for testing purposes.
     10
     11        This facility is only conditionally compiled in on debug builds.  It does not
     12        have any burden on release builds at all.  When in use, the max single allocation
     13        size limit applies to individual allocations.  For malloc (and similar), the
     14        allocation will crash in FastMalloc if the requested size exceeds the set max
     15        single allocation size.  For tryMalloc (and similar), the allocation returns
     16        nullptr if the requested size exceeds the set max single allocation size.  The
     17        max single allocation size is set to std::numeric_limit<size_t>::max() by default
     18        (i.e. when not set and no limit is in effect).
     19
     20        Also fixed non-bmalloc versions of fastAlignedMalloc() to crash when allocation
     21        fails.
     22
     23        * wtf/FastMalloc.cpp:
     24        (WTF::fastSetMaxSingleAllocationSize):
     25        (WTF::fastAlignedMalloc):
     26        (WTF::tryFastAlignedMalloc):
     27        (WTF::tryFastMalloc):
     28        (WTF::fastMalloc):
     29        (WTF::tryFastCalloc):
     30        (WTF::fastCalloc):
     31        (WTF::fastRealloc):
     32        * wtf/FastMalloc.h:
     33
    1342016-11-13  JF Bastien  <jfbastien@apple.com>
    235
  • trunk/Source/WTF/wtf/FastMalloc.cpp

    r205462 r208690  
    4747namespace WTF {
    4848
     49#if !defined(NDEBUG)
     50namespace {
     51size_t maxSingleAllocationSize = std::numeric_limits<size_t>::max();
     52};
     53
     54void fastSetMaxSingleAllocationSize(size_t size)
     55{
     56    maxSingleAllocationSize = size;
     57}
     58
     59#define ASSERT_IS_WITHIN_LIMIT(size) do { \
     60        size_t size__ = (size); \
     61        ASSERT_WITH_MESSAGE((size__) <= maxSingleAllocationSize, "Requested size (%zu) exceeds max single allocation size set for testing (%zu)", (size__), maxSingleAllocationSize); \
     62    } while (false)
     63
     64#define FAIL_IF_EXCEEDS_LIMIT(size) do { \
     65        if (UNLIKELY((size) > maxSingleAllocationSize)) \
     66            return nullptr; \
     67    } while (false)
     68
     69#else // !defined(NDEBUG)
     70
     71#define ASSERT_IS_WITHIN_LIMIT(size)
     72#define FAIL_IF_EXCEEDS_LIMIT(size)
     73
     74#endif // !defined(NDEBUG)
     75
    4976void* fastZeroedMalloc(size_t n)
    5077{
     
    99126void* fastAlignedMalloc(size_t alignment, size_t size)
    100127{
     128    ASSERT_IS_WITHIN_LIMIT(size);
     129    void* p = _aligned_malloc(size, alignment);
     130    if (UNLIKELY(!p))
     131        CRASH();
     132    return p;
     133}
     134
     135void* tryFastAlignedMalloc(size_t alignment, size_t size)
     136{
     137    FAIL_IF_EXCEEDS_LIMIT(size);
    101138    return _aligned_malloc(size, alignment);
    102139}
    103140
     141void fastAlignedFree(void* p)
     142{
     143    _aligned_free(p);
     144}
     145
     146#else
     147
     148void* fastAlignedMalloc(size_t alignment, size_t size)
     149{
     150    ASSERT_IS_WITHIN_LIMIT(size);
     151    void* p = nullptr;
     152    posix_memalign(&p, alignment, size);
     153    if (UNLIKELY(!p))
     154        CRASH();
     155    return p;
     156}
     157
    104158void* tryFastAlignedMalloc(size_t alignment, size_t size)
    105159{
    106     return _aligned_malloc(size, alignment);
    107 }
    108 
    109 void fastAlignedFree(void* p)
    110 {
    111     _aligned_free(p);
    112 }
    113 
    114 #else
    115 
    116 void* fastAlignedMalloc(size_t alignment, size_t size)
    117 {
     160    FAIL_IF_EXCEEDS_LIMIT(size);
    118161    void* p = nullptr;
    119162    posix_memalign(&p, alignment, size);
     
    121164}
    122165
    123 void* tryFastAlignedMalloc(size_t alignment, size_t size)
    124 {
    125     void* p = nullptr;
    126     posix_memalign(&p, alignment, size);
    127     return p;
    128 }
    129 
    130166void fastAlignedFree(void* p)
    131167{
     
    137173TryMallocReturnValue tryFastMalloc(size_t n)
    138174{
     175    FAIL_IF_EXCEEDS_LIMIT(n);
    139176    return malloc(n);
    140177}
     
    142179void* fastMalloc(size_t n)
    143180{
     181    ASSERT_IS_WITHIN_LIMIT(n);
    144182    void* result = malloc(n);
    145183    if (!result)
     
    151189TryMallocReturnValue tryFastCalloc(size_t n_elements, size_t element_size)
    152190{
     191    FAIL_IF_EXCEEDS_LIMIT(n_elements * element_size);
    153192    return calloc(n_elements, element_size);
    154193}
     
    156195void* fastCalloc(size_t n_elements, size_t element_size)
    157196{
     197    ASSERT_IS_WITHIN_LIMIT(n_elements * element_size);
    158198    void* result = calloc(n_elements, element_size);
    159199    if (!result)
     
    170210void* fastRealloc(void* p, size_t n)
    171211{
     212    ASSERT_IS_WITHIN_LIMIT(n);
    172213    void* result = realloc(p, n);
    173214    if (!result)
     
    212253void* fastMalloc(size_t size)
    213254{
     255    ASSERT_IS_WITHIN_LIMIT(size);
    214256    return bmalloc::api::malloc(size);
    215257}
     
    217259void* fastCalloc(size_t numElements, size_t elementSize)
    218260{
     261    ASSERT_IS_WITHIN_LIMIT(numElements * elementSize);
    219262    Checked<size_t> checkedSize = elementSize;
    220263    checkedSize *= numElements;
     
    227270void* fastRealloc(void* object, size_t size)
    228271{
     272    ASSERT_IS_WITHIN_LIMIT(size);
    229273    return bmalloc::api::realloc(object, size);
    230274}
     
    250294void* fastAlignedMalloc(size_t alignment, size_t size)
    251295{
     296    ASSERT_IS_WITHIN_LIMIT(size);
    252297    return bmalloc::api::memalign(alignment, size);
    253298}
     
    255300void* tryFastAlignedMalloc(size_t alignment, size_t size)
    256301{
     302    FAIL_IF_EXCEEDS_LIMIT(size);
    257303    return bmalloc::api::tryMemalign(alignment, size);
    258304}
     
    265311TryMallocReturnValue tryFastMalloc(size_t size)
    266312{
     313    FAIL_IF_EXCEEDS_LIMIT(size);
    267314    return bmalloc::api::tryMalloc(size);
    268315}
     
    270317TryMallocReturnValue tryFastCalloc(size_t numElements, size_t elementSize)
    271318{
     319    FAIL_IF_EXCEEDS_LIMIT(numElements * elementSize);
    272320    Checked<size_t, RecordOverflow> checkedSize = elementSize;
    273321    checkedSize *= numElements;
  • trunk/Source/WTF/wtf/FastMalloc.h

    r205462 r208690  
    2727
    2828namespace WTF {
     29
     30#if !defined(NDEBUG)
     31void fastSetMaxSingleAllocationSize(size_t);
     32#endif
    2933
    3034class TryMallocReturnValue {
     
    103107} // namespace WTF
    104108
     109#if !defined(NDEBUG)
     110using WTF::fastSetMaxSingleAllocationSize;
     111#endif
     112
    105113using WTF::isFastMallocEnabled;
    106114using WTF::fastCalloc;
Note: See TracChangeset for help on using the changeset viewer.