]> git.saurik.com Git - apple/javascriptcore.git/blame - runtime/MapData.h
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / runtime / MapData.h
CommitLineData
81345200
A
1/*
2 * Copyright (C) 2013 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#ifndef MapData_h
27#define MapData_h
28
29#include "JSCell.h"
ed1e77d3 30#include "WeakGCMapInlines.h"
81345200
A
31#include <wtf/HashFunctions.h>
32#include <wtf/HashMap.h>
33#include <wtf/MathExtras.h>
ed1e77d3
A
34#include <wtf/RefCounted.h>
35#include <wtf/RefPtr.h>
36#include <wtf/Vector.h>
81345200
A
37
38namespace JSC {
39
ed1e77d3
A
40class ExecState;
41class VM;
42
43template<typename Entry, typename JSIterator>
44class MapDataImpl {
81345200 45public:
ed1e77d3
A
46 enum : int32_t {
47 minimumMapSize = 8
48 };
49
50 class IteratorData {
51 public:
52 friend class MapDataImpl;
53
54 IteratorData(const MapDataImpl*);
55 bool next(WTF::KeyValuePair<JSValue, JSValue>&);
56
57 // This function is called while packing a map's backing store. The
58 // passed-in index is the new index the entry would have after packing.
59 void didRemoveEntry(int32_t packedIndex)
60 {
61 if (isFinished())
62 return;
81345200 63
ed1e77d3
A
64 if (m_index <= packedIndex)
65 return;
81345200 66
ed1e77d3
A
67 --m_index;
68 }
69
70 void didRemoveAllEntries()
71 {
72 if (isFinished())
73 return;
74 m_index = 0;
75 }
76
77 void finish()
78 {
79 m_index = -1;
80 }
81345200
A
81
82 private:
ed1e77d3
A
83 bool ensureSlot() const;
84 bool isFinished() const { return m_index == -1; }
85 int32_t refreshCursor() const;
86
87 const MapDataImpl* m_mapData;
88 mutable int32_t m_index;
81345200
A
89 };
90
91 struct KeyType {
92 ALWAYS_INLINE KeyType() { }
93 KeyType(JSValue);
94 JSValue value;
95 };
96
ed1e77d3 97 MapDataImpl(VM&);
81345200 98
ed1e77d3
A
99 void set(ExecState*, JSCell* owner, KeyType, JSValue);
100 JSValue get(ExecState*, KeyType);
101 bool remove(ExecState*, KeyType);
102 bool contains(ExecState*, KeyType);
103 size_t size(ExecState*) const { return m_size - m_deletedCount; }
81345200 104
ed1e77d3 105 IteratorData createIteratorData(JSIterator*);
81345200
A
106
107 void clear();
108
ed1e77d3
A
109 void visitChildren(JSCell* owner, SlotVisitor&);
110 void copyBackingStore(CopyVisitor&, CopyToken);
81345200
A
111
112private:
113 typedef WTF::UnsignedWithZeroKeyHashTraits<int32_t> IndexTraits;
114
81345200
A
115 typedef HashMap<JSCell*, int32_t, typename WTF::DefaultHash<JSCell*>::Hash, WTF::HashTraits<JSCell*>, IndexTraits> CellKeyedMap;
116 typedef HashMap<EncodedJSValue, int32_t, EncodedJSValueHash, EncodedJSValueHashTraits, IndexTraits> ValueKeyedMap;
117 typedef HashMap<StringImpl*, int32_t, typename WTF::DefaultHash<StringImpl*>::Hash, WTF::HashTraits<StringImpl*>, IndexTraits> StringKeyedMap;
ed1e77d3 118 typedef HashMap<SymbolImpl*, int32_t, typename WTF::PtrHash<SymbolImpl*>, WTF::HashTraits<SymbolImpl*>, IndexTraits> SymbolKeyedMap;
81345200
A
119
120 size_t capacityInBytes() { return m_capacity * sizeof(Entry); }
121
ed1e77d3
A
122 ALWAYS_INLINE Entry* find(ExecState*, KeyType);
123 ALWAYS_INLINE Entry* add(ExecState*, JSCell* owner, KeyType);
124 template <typename Map, typename Key> ALWAYS_INLINE Entry* add(ExecState*, JSCell* owner, Map&, Key, KeyType);
81345200 125
ed1e77d3
A
126 ALWAYS_INLINE bool shouldPack() const { return m_deletedCount; }
127 CheckedBoolean ensureSpaceForAppend(ExecState*, JSCell* owner);
81345200
A
128
129 ALWAYS_INLINE void replaceAndPackBackingStore(Entry* destination, int32_t newSize);
130 ALWAYS_INLINE void replaceBackingStore(Entry* destination, int32_t newSize);
131
132 CellKeyedMap m_cellKeyedTable;
133 ValueKeyedMap m_valueKeyedTable;
134 StringKeyedMap m_stringKeyedTable;
ed1e77d3 135 SymbolKeyedMap m_symbolKeyedTable;
81345200
A
136 int32_t m_capacity;
137 int32_t m_size;
138 int32_t m_deletedCount;
81345200 139 Entry* m_entries;
ed1e77d3 140 WeakGCMap<JSIterator*, JSIterator> m_iterators;
81345200
A
141};
142
ed1e77d3
A
143template<typename Entry, typename JSIterator>
144ALWAYS_INLINE MapDataImpl<Entry, JSIterator>::MapDataImpl(VM& vm)
145 : m_capacity(0)
146 , m_size(0)
147 , m_deletedCount(0)
148 , m_entries(nullptr)
149 , m_iterators(vm)
81345200 150{
81345200
A
151}
152
ed1e77d3
A
153template<typename Entry, typename JSIterator>
154ALWAYS_INLINE MapDataImpl<Entry, JSIterator>::KeyType::KeyType(JSValue v)
81345200
A
155{
156 if (!v.isDouble()) {
157 value = v;
158 return;
159 }
160 double d = v.asDouble();
ed1e77d3 161 if (std::isnan(d)) {
81345200
A
162 value = v;
163 return;
164 }
165
166 int i = static_cast<int>(v.asDouble());
167 if (i != d)
168 value = v;
169 else
170 value = jsNumber(i);
171}
172
ed1e77d3
A
173template<typename Entry, typename JSIterator>
174ALWAYS_INLINE MapDataImpl<Entry, JSIterator>::IteratorData::IteratorData(const MapDataImpl<Entry, JSIterator>* mapData)
81345200 175 : m_mapData(mapData)
ed1e77d3 176 , m_index(0)
81345200 177{
81345200
A
178}
179
ed1e77d3
A
180template<typename Entry, typename JSIterator>
181ALWAYS_INLINE bool MapDataImpl<Entry, JSIterator>::IteratorData::next(WTF::KeyValuePair<JSValue, JSValue>& pair)
81345200 182{
ed1e77d3
A
183 if (!ensureSlot())
184 return false;
81345200 185 Entry* entry = &m_mapData->m_entries[m_index];
ed1e77d3
A
186 pair = WTF::KeyValuePair<JSValue, JSValue>(entry->key().get(), entry->value().get());
187 m_index += 1;
188 return true;
81345200
A
189}
190
ed1e77d3
A
191// This is a bit gnarly. We use an index of -1 to indicate the
192// finished state. By casting to unsigned we can immediately
193// test if both iterators are at the end of their iteration.
194template<typename Entry, typename JSIterator>
195ALWAYS_INLINE bool MapDataImpl<Entry, JSIterator>::IteratorData::ensureSlot() const
81345200 196{
ed1e77d3
A
197 int32_t index = refreshCursor();
198 return static_cast<size_t>(index) < static_cast<size_t>(m_mapData->m_size);
81345200
A
199}
200
ed1e77d3
A
201template<typename Entry, typename JSIterator>
202ALWAYS_INLINE int32_t MapDataImpl<Entry, JSIterator>::IteratorData::refreshCursor() const
81345200 203{
ed1e77d3
A
204 if (isFinished())
205 return m_index;
81345200 206
ed1e77d3
A
207 Entry* entries = m_mapData->m_entries;
208 size_t end = m_mapData->m_size;
209 while (static_cast<size_t>(m_index) < end && !entries[m_index].key())
210 m_index++;
211 return m_index;
81345200
A
212}
213
214}
215
216#endif /* !defined(MapData_h) */