2 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
30 #include "WeakGCMapInlines.h"
31 #include <wtf/HashFunctions.h>
32 #include <wtf/HashMap.h>
33 #include <wtf/MathExtras.h>
34 #include <wtf/RefCounted.h>
35 #include <wtf/RefPtr.h>
36 #include <wtf/Vector.h>
43 template<typename Entry
, typename JSIterator
>
52 friend class MapDataImpl
;
54 IteratorData(const MapDataImpl
*);
55 bool next(WTF::KeyValuePair
<JSValue
, JSValue
>&);
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
)
64 if (m_index
<= packedIndex
)
70 void didRemoveAllEntries()
83 bool ensureSlot() const;
84 bool isFinished() const { return m_index
== -1; }
85 int32_t refreshCursor() const;
87 const MapDataImpl
* m_mapData
;
88 mutable int32_t m_index
;
92 ALWAYS_INLINE
KeyType() { }
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
; }
105 IteratorData
createIteratorData(JSIterator
*);
109 void visitChildren(JSCell
* owner
, SlotVisitor
&);
110 void copyBackingStore(CopyVisitor
&, CopyToken
);
113 typedef WTF::UnsignedWithZeroKeyHashTraits
<int32_t> IndexTraits
;
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
;
118 typedef HashMap
<SymbolImpl
*, int32_t, typename
WTF::PtrHash
<SymbolImpl
*>, WTF::HashTraits
<SymbolImpl
*>, IndexTraits
> SymbolKeyedMap
;
120 size_t capacityInBytes() { return m_capacity
* sizeof(Entry
); }
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
);
126 ALWAYS_INLINE
bool shouldPack() const { return m_deletedCount
; }
127 CheckedBoolean
ensureSpaceForAppend(ExecState
*, JSCell
* owner
);
129 ALWAYS_INLINE
void replaceAndPackBackingStore(Entry
* destination
, int32_t newSize
);
130 ALWAYS_INLINE
void replaceBackingStore(Entry
* destination
, int32_t newSize
);
132 CellKeyedMap m_cellKeyedTable
;
133 ValueKeyedMap m_valueKeyedTable
;
134 StringKeyedMap m_stringKeyedTable
;
135 SymbolKeyedMap m_symbolKeyedTable
;
138 int32_t m_deletedCount
;
140 WeakGCMap
<JSIterator
*, JSIterator
> m_iterators
;
143 template<typename Entry
, typename JSIterator
>
144 ALWAYS_INLINE MapDataImpl
<Entry
, JSIterator
>::MapDataImpl(VM
& vm
)
153 template<typename Entry
, typename JSIterator
>
154 ALWAYS_INLINE MapDataImpl
<Entry
, JSIterator
>::KeyType::KeyType(JSValue v
)
160 double d
= v
.asDouble();
166 int i
= static_cast<int>(v
.asDouble());
173 template<typename Entry
, typename JSIterator
>
174 ALWAYS_INLINE MapDataImpl
<Entry
, JSIterator
>::IteratorData::IteratorData(const MapDataImpl
<Entry
, JSIterator
>* mapData
)
180 template<typename Entry
, typename JSIterator
>
181 ALWAYS_INLINE
bool MapDataImpl
<Entry
, JSIterator
>::IteratorData::next(WTF::KeyValuePair
<JSValue
, JSValue
>& pair
)
185 Entry
* entry
= &m_mapData
->m_entries
[m_index
];
186 pair
= WTF::KeyValuePair
<JSValue
, JSValue
>(entry
->key().get(), entry
->value().get());
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.
194 template<typename Entry
, typename JSIterator
>
195 ALWAYS_INLINE
bool MapDataImpl
<Entry
, JSIterator
>::IteratorData::ensureSlot() const
197 int32_t index
= refreshCursor();
198 return static_cast<size_t>(index
) < static_cast<size_t>(m_mapData
->m_size
);
201 template<typename Entry
, typename JSIterator
>
202 ALWAYS_INLINE
int32_t MapDataImpl
<Entry
, JSIterator
>::IteratorData::refreshCursor() const
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())
216 #endif /* !defined(MapData_h) */