1/*
2 * Copyright (C) 2006, 2008, 2012 Apple Inc. All rights reserved.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public License
15 * along with this library; see the file COPYING.LIB. If not, write to
16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 *
19 */
20
21#ifndef PropertyNameArray_h
22#define PropertyNameArray_h
23
24#include "CallFrame.h"
25#include "Identifier.h"
26#include <wtf/HashSet.h>
27#include <wtf/Vector.h>
28
29namespace JSC {
30
31// FIXME: Rename to PropertyNameArray.
32class PropertyNameArrayData : public RefCounted<PropertyNameArrayData> {
33public:
34 typedef Vector<Identifier, 20> PropertyNameVector;
35
36 static Ref<PropertyNameArrayData> create() { return adoptRef(*new PropertyNameArrayData); }
37
38 PropertyNameVector& propertyNameVector() { return m_propertyNameVector; }
39
40private:
41 PropertyNameArrayData()
42 {
43 }
44
45 PropertyNameVector m_propertyNameVector;
46};
47
48// FIXME: Rename to PropertyNameArrayBuilder.
49class PropertyNameArray {
50public:
51 PropertyNameArray(VM* vm, PropertyNameMode mode)
52 : m_data(PropertyNameArrayData::create())
53 , m_vm(vm)
54 , m_mode(mode)
55 {
56 }
57
58 PropertyNameArray(ExecState* exec, PropertyNameMode mode)
59 : PropertyNameArray(&exec->vm(), mode)
60 {
61 }
62
63 VM* vm() { return m_vm; }
64
65 void add(uint32_t index)
66 {
67 add(Identifier::from(m_vm, index));
68 }
69
70 void add(const Identifier&);
71 void add(UniquedStringImpl*);
72 void addKnownUnique(UniquedStringImpl*);
73
74 Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
75 const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; }
76
77 void setData(PassRefPtr<PropertyNameArrayData> data) { m_data = data; }
78 PropertyNameArrayData* data() { return m_data.get(); }
79 PassRefPtr<PropertyNameArrayData> releaseData() { return m_data.release(); }
80
81 // FIXME: Remove these functions.
82 bool canAddKnownUniqueForStructure() const { return m_data->propertyNameVector().isEmpty(); }
83 typedef PropertyNameArrayData::PropertyNameVector::const_iterator const_iterator;
84 size_t size() const { return m_data->propertyNameVector().size(); }
85 const_iterator begin() const { return m_data->propertyNameVector().begin(); }
86 const_iterator end() const { return m_data->propertyNameVector().end(); }
87
88 PropertyNameMode mode() const { return m_mode; }
89 bool includeSymbolProperties() const;
90 bool includeStringProperties() const;
91
92private:
93 bool isUidMatchedToTypeMode(UniquedStringImpl* identifier);
94
95 RefPtr<PropertyNameArrayData> m_data;
96 HashSet<UniquedStringImpl*> m_set;
97 VM* m_vm;
98 PropertyNameMode m_mode;
99};
100
101ALWAYS_INLINE void PropertyNameArray::add(const Identifier& identifier)
102{
103 add(identifier.impl());
104}
105
106ALWAYS_INLINE void PropertyNameArray::addKnownUnique(UniquedStringImpl* identifier)
107{
108 if (!isUidMatchedToTypeMode(identifier))
109 return;
110 m_data->propertyNameVector().append(Identifier::fromUid(m_vm, identifier));
111}
112
113ALWAYS_INLINE void PropertyNameArray::add(UniquedStringImpl* identifier)
114{
115 static const unsigned setThreshold = 20;
116
117 ASSERT(identifier);
118
119 if (!isUidMatchedToTypeMode(identifier))
120 return;
121
122 if (size() < setThreshold) {
123 if (m_data->propertyNameVector().contains(identifier))
124 return;
125 } else {
126 if (m_set.isEmpty()) {
127 for (Identifier& name : m_data->propertyNameVector())
128 m_set.add(name.impl());
129 }
130 if (!m_set.add(identifier).isNewEntry)
131 return;
132 }
133
134 addKnownUnique(identifier);
135}
136
137ALWAYS_INLINE bool PropertyNameArray::isUidMatchedToTypeMode(UniquedStringImpl* identifier)
138{
139 if (identifier->isSymbol())
140 return includeSymbolProperties();
141 return includeStringProperties();
142}
143
144ALWAYS_INLINE bool PropertyNameArray::includeSymbolProperties() const
145{
146 return static_cast<std::underlying_type<PropertyNameMode>::type>(m_mode) & static_cast<std::underlying_type<PropertyNameMode>::type>(PropertyNameMode::Symbols);
147}
148
149ALWAYS_INLINE bool PropertyNameArray::includeStringProperties() const
150{
151 return static_cast<std::underlying_type<PropertyNameMode>::type>(m_mode) & static_cast<std::underlying_type<PropertyNameMode>::type>(PropertyNameMode::Strings);
152}
153
154} // namespace JSC
155
156#endif // PropertyNameArray_h
157