Changeset 234879 in webkit


Ignore:
Timestamp:
Aug 14, 2018 9:08:08 PM (6 years ago)
Author:
sbarati@apple.com
Message:

HashMap<Ref<P>, V> asserts when V is not zero for its empty value
https://bugs.webkit.org/show_bug.cgi?id=188582

Reviewed by Sam Weinig.

Source/JavaScriptCore:

  • runtime/SparseArrayValueMap.h:

Source/WTF:

The issue happened when we'd fill the hash table buffer with empty values. We
would iterate the buffer and invoke placement new with the incoming value being the
empty value. For Ref, this means that, we'd call its move constructor, which calls
leakRef(), which asserts that the Ref's pointer is not null. We'd like to keep
this assert since it catches bugs where you leakRef() more than once or WTFMove
an already moved Ref.

This patch fixes this issue by adding a new trait for constructing an empty
value. We use that in HashTable instead of directly calling placement new.

  • wtf/HashTable.h:

(WTF::HashTableBucketInitializer<false>::initialize):

  • wtf/HashTraits.h:

(WTF::GenericHashTraits::constructEmptyValue):
(WTF::HashTraits<Ref<P>>::constructEmptyValue):
(WTF::KeyValuePairHashTraits::constructEmptyValue):

Tools:

  • TestWebKitAPI/Tests/WTF/HashMap.cpp:

(TestWebKitAPI::TEST):

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r234876 r234879  
     12018-08-14  Saam barati  <sbarati@apple.com>
     2
     3        HashMap<Ref<P>, V> asserts when V is not zero for its empty value
     4        https://bugs.webkit.org/show_bug.cgi?id=188582
     5
     6        Reviewed by Sam Weinig.
     7
     8        * runtime/SparseArrayValueMap.h:
     9
    1102018-08-14  Yusuke Suzuki  <yusukesuzuki@slowstart.org>
    211
  • trunk/Source/JavaScriptCore/runtime/SparseArrayValueMap.h

    r234089 r234879  
    3838
    3939class SparseArrayEntry : private WriteBarrier<Unknown> {
     40    WTF_MAKE_FAST_ALLOCATED;
    4041public:
    4142    using Base = WriteBarrier<Unknown>;
  • trunk/Source/WTF/ChangeLog

    r234877 r234879  
     12018-08-14  Saam barati  <sbarati@apple.com>
     2
     3        HashMap<Ref<P>, V> asserts when V is not zero for its empty value
     4        https://bugs.webkit.org/show_bug.cgi?id=188582
     5
     6        Reviewed by Sam Weinig.
     7
     8        The issue happened when we'd fill the hash table buffer with empty values. We
     9        would iterate the buffer and invoke placement new with the incoming value being the
     10        empty value. For Ref, this means that, we'd call its move constructor, which calls
     11        leakRef(), which asserts that the Ref's pointer is not null. We'd like to keep
     12        this assert since it catches bugs where you leakRef() more than once or WTFMove
     13        an already moved Ref.
     14       
     15        This patch fixes this issue by adding a new trait for constructing an empty
     16        value. We use that in HashTable instead of directly calling placement new.
     17
     18        * wtf/HashTable.h:
     19        (WTF::HashTableBucketInitializer<false>::initialize):
     20        * wtf/HashTraits.h:
     21        (WTF::GenericHashTraits::constructEmptyValue):
     22        (WTF::HashTraits<Ref<P>>::constructEmptyValue):
     23        (WTF::KeyValuePairHashTraits::constructEmptyValue):
     24
    1252018-08-14  Fujii Hironori  <Hironori.Fujii@sony.com>
    226
  • trunk/Source/WTF/wtf/HashTable.h

    r231565 r234879  
    838838        template<typename Traits, typename Value> static void initialize(Value& bucket)
    839839        {
    840             new (NotNull, std::addressof(bucket)) Value(Traits::emptyValue());
     840            Traits::template constructEmptyValue<Traits>(bucket);
    841841        }
    842842    };
  • trunk/Source/WTF/wtf/HashTraits.h

    r234685 r234879  
    7171    }
    7272
     73    template <typename Traits>
     74    static void constructEmptyValue(T& slot)
     75    {
     76        new (NotNull, std::addressof(slot)) T(Traits::emptyValue());
     77    }
     78
    7379    // Type for return value of functions that do not transfer ownership, such as get.
    7480    typedef T PeekType;
     
    192198    static Ref<P> emptyValue() { return HashTableEmptyValue; }
    193199
     200    template <typename>
     201    static void constructEmptyValue(Ref<P>& slot)
     202    {
     203        new (NotNull, std::addressof(slot)) Ref<P>(HashTableEmptyValue);
     204    }
     205
    194206    static const bool hasIsEmptyValueFunction = true;
    195207    static bool isEmptyValue(const Ref<P>& value) { return value.isHashTableEmptyValue(); }
     
    303315    static EmptyValueType emptyValue() { return KeyValuePair<typename KeyTraits::EmptyValueType, typename ValueTraits::EmptyValueType>(KeyTraits::emptyValue(), ValueTraits::emptyValue()); }
    304316
     317    template <typename>
     318    static void constructEmptyValue(TraitType& slot)
     319    {
     320        KeyTraits::template constructEmptyValue<KeyTraits>(slot.key);
     321        ValueTraits::template constructEmptyValue<ValueTraits>(slot.value);
     322    }
     323
    305324    static const unsigned minimumTableSize = KeyTraits::minimumTableSize;
    306325
  • trunk/Tools/ChangeLog

    r234878 r234879  
     12018-08-14  Saam barati  <sbarati@apple.com>
     2
     3        HashMap<Ref<P>, V> asserts when V is not zero for its empty value
     4        https://bugs.webkit.org/show_bug.cgi?id=188582
     5
     6        Reviewed by Sam Weinig.
     7
     8        * TestWebKitAPI/Tests/WTF/HashMap.cpp:
     9        (TestWebKitAPI::TEST):
     10
    1112018-08-14  Zalan Bujtas  <zalan@apple.com>
    212
  • trunk/Tools/TestWebKitAPI/Tests/WTF/HashMap.cpp

    r217938 r234879  
    946946}
    947947
     948TEST(WTF_HashMap, RefMappedToNonZeroEmptyValue)
     949{
     950    class Value {
     951    public:
     952        Value() = default;
     953        Value(Value&&) = default;
     954        Value(const Value&) = default;
     955        Value& operator=(Value&&) = default;
     956
     957        Value(int32_t f)
     958            : m_field(f)
     959        { }
     960
     961        int32_t field() { return m_field; }
     962
     963    private:
     964        int32_t m_field { 0xbadbeef };
     965    };
     966
     967    class Key : public RefCounted<Key> {
     968        Key() = default;
     969    public:
     970        static Ref<Key> create() { return adoptRef(*new Key); }
     971    };
     972
     973    static_assert(!WTF::HashTraits<Value>::emptyValueIsZero, "");
     974
     975    HashMap<Ref<Key>, Value> map;
     976    Vector<std::pair<Ref<Key>, int32_t>> vectorMap;
     977
     978    for (int32_t i = 0; i < 160; ++i) {
     979        Ref<Key> key = Key::create();
     980        map.add(Ref<Key>(key.get()), Value { i });
     981        vectorMap.append({ WTFMove(key), i });
     982    }
     983
     984    for (auto& pair : vectorMap)
     985        ASSERT_EQ(pair.second, map.get(pair.first).field());
     986
     987    for (auto& pair : vectorMap)
     988        ASSERT_TRUE(map.remove(pair.first));
     989}
     990
    948991} // namespace TestWebKitAPI
Note: See TracChangeset for help on using the changeset viewer.