1/*
2 * Copyright (C) 2015 Yusuke Suzuki <[email protected]>.
3 * Copyright (C) 2019 Apple Inc. All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
16 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
18 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
24 * THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#pragma once
28
29#include <wtf/HashSet.h>
30#include <wtf/text/StringHash.h>
31#include <wtf/text/SymbolImpl.h>
32#include <wtf/text/WTFString.h>
33
34namespace WTF {
35
36// Since StringImpl* used for Symbol uid doesn't have a hash value reflecting the string content,
37// to compare with an external string in string contents, introduce SymbolRegistryKey.
38// SymbolRegistryKey holds a hash value reflecting the string content additionally.
39class SymbolRegistryKey {
40public:
41 SymbolRegistryKey() = default;
42 explicit SymbolRegistryKey(StringImpl* uid);
43 SymbolRegistryKey(WTF::HashTableDeletedValueType);
44
45 unsigned hash() const { return m_hash; }
46 StringImpl* impl() const { return m_impl; }
47
48 bool isHashTableDeletedValue() const { return m_impl == hashTableDeletedValue(); }
49
50private:
51 static StringImpl* hashTableDeletedValue() { return reinterpret_cast<StringImpl*>(-1); }
52
53 StringImpl* m_impl { nullptr };
54 unsigned m_hash { 0 };
55};
56
57template<typename T> struct DefaultHash;
58template<> struct DefaultHash<SymbolRegistryKey> {
59 struct Hash : StringHash {
60 static unsigned hash(const SymbolRegistryKey& key)
61 {
62 return key.hash();
63 }
64 static bool equal(const SymbolRegistryKey& a, const SymbolRegistryKey& b)
65 {
66 return StringHash::equal(a.impl(), b.impl());
67 }
68 };
69};
70
71template<> struct HashTraits<SymbolRegistryKey> : SimpleClassHashTraits<SymbolRegistryKey> {
72 static constexpr bool hasIsEmptyValueFunction = true;
73 static bool isEmptyValue(const SymbolRegistryKey& key)
74 {
75 return key.impl() == nullptr;
76 }
77};
78
79class SymbolRegistry {
80 WTF_MAKE_FAST_ALLOCATED;
81 WTF_MAKE_NONCOPYABLE(SymbolRegistry);
82public:
83 SymbolRegistry() = default;
84 WTF_EXPORT_PRIVATE ~SymbolRegistry();
85
86 WTF_EXPORT_PRIVATE Ref<RegisteredSymbolImpl> symbolForKey(const String&);
87
88 void remove(RegisteredSymbolImpl&);
89
90private:
91 HashSet<SymbolRegistryKey> m_table;
92};
93
94inline SymbolRegistryKey::SymbolRegistryKey(StringImpl* uid)
95 : m_impl(uid)
96{
97 if (uid->isSymbol()) {
98 if (uid->is8Bit())
99 m_hash = StringHasher::computeHashAndMaskTop8Bits(uid->characters8(), uid->length());
100 else
101 m_hash = StringHasher::computeHashAndMaskTop8Bits(uid->characters16(), uid->length());
102 } else
103 m_hash = uid->hash();
104}
105
106inline SymbolRegistryKey::SymbolRegistryKey(WTF::HashTableDeletedValueType)
107 : m_impl(hashTableDeletedValue())
108{
109}
110
111}
112