1/*
2 * Copyright (C) 2006-2019 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#pragma once
22
23#include "Identifier.h"
24#include <wtf/HashSet.h>
25#include <wtf/Vector.h>
26
27namespace JSC {
28
29// FIXME: Rename to PropertyNameArray.
30class PropertyNameArrayData : public RefCounted<PropertyNameArrayData> {
31public:
32 typedef Vector<Identifier, 20> PropertyNameVector;
33
34 static Ref<PropertyNameArrayData> create() { return adoptRef(*new PropertyNameArrayData); }
35
36 PropertyNameVector& propertyNameVector() { return m_propertyNameVector; }
37
38private:
39 PropertyNameArrayData()
40 {
41 }
42
43 PropertyNameVector m_propertyNameVector;
44};
45
46// FIXME: Rename to PropertyNameArrayBuilder.
47class PropertyNameArray {
48public:
49 PropertyNameArray(VM& vm, PropertyNameMode propertyNameMode, PrivateSymbolMode privateSymbolMode)
50 : m_data(PropertyNameArrayData::create())
51 , m_vm(vm)
52 , m_propertyNameMode(propertyNameMode)
53 , m_privateSymbolMode(privateSymbolMode)
54 {
55 }
56
57 VM& vm() { return m_vm; }
58
59 void add(uint32_t index)
60 {
61 add(Identifier::from(m_vm, index));
62 }
63
64 void add(const Identifier&);
65 void add(UniquedStringImpl*);
66 void addUnchecked(UniquedStringImpl*);
67
68 Identifier& operator[](unsigned i) { return m_data->propertyNameVector()[i]; }
69 const Identifier& operator[](unsigned i) const { return m_data->propertyNameVector()[i]; }
70
71 PropertyNameArrayData* data() { return m_data.get(); }
72 RefPtr<PropertyNameArrayData> releaseData() { return WTFMove(m_data); }
73
74 // FIXME: Remove these functions.
75 bool canAddKnownUniqueForStructure() const { return m_data->propertyNameVector().isEmpty(); }
76 typedef PropertyNameArrayData::PropertyNameVector::const_iterator const_iterator;
77 size_t size() const { return m_data->propertyNameVector().size(); }
78 const_iterator begin() const { return m_data->propertyNameVector().begin(); }
79 const_iterator end() const { return m_data->propertyNameVector().end(); }
80
81 bool includeSymbolProperties() const;
82 bool includeStringProperties() const;
83
84 PropertyNameMode propertyNameMode() const { return m_propertyNameMode; }
85 PrivateSymbolMode privateSymbolMode() const { return m_privateSymbolMode; }
86
87private:
88 void addUncheckedInternal(UniquedStringImpl*);
89 bool isUidMatchedToTypeMode(UniquedStringImpl* identifier);
90
91 RefPtr<PropertyNameArrayData> m_data;
92 HashSet<UniquedStringImpl*> m_set;
93 VM& m_vm;
94 PropertyNameMode m_propertyNameMode;
95 PrivateSymbolMode m_privateSymbolMode;
96};
97
98ALWAYS_INLINE void PropertyNameArray::add(const Identifier& identifier)
99{
100 add(identifier.impl());
101}
102
103ALWAYS_INLINE void PropertyNameArray::addUncheckedInternal(UniquedStringImpl* identifier)
104{
105 m_data->propertyNameVector().append(Identifier::fromUid(m_vm, identifier));
106}
107
108ALWAYS_INLINE void PropertyNameArray::addUnchecked(UniquedStringImpl* identifier)
109{
110 if (!isUidMatchedToTypeMode(identifier))
111 return;
112 addUncheckedInternal(identifier);
113}
114
115ALWAYS_INLINE void PropertyNameArray::add(UniquedStringImpl* identifier)
116{
117 static constexpr unsigned setThreshold = 20;
118
119 ASSERT(identifier);
120
121 if (!isUidMatchedToTypeMode(identifier))
122 return;
123
124 if (size() < setThreshold) {
125 if (m_data->propertyNameVector().contains(identifier))
126 return;
127 } else {
128 if (m_set.isEmpty()) {
129 for (Identifier& name : m_data->propertyNameVector())
130 m_set.add(name.impl());
131 }
132 if (!m_set.add(identifier).isNewEntry)
133 return;
134 }
135
136 addUncheckedInternal(identifier);
137}
138
139ALWAYS_INLINE bool PropertyNameArray::isUidMatchedToTypeMode(UniquedStringImpl* identifier)
140{
141 if (identifier->isSymbol()) {
142 if (!includeSymbolProperties())
143 return false;
144 if (UNLIKELY(m_privateSymbolMode == PrivateSymbolMode::Include))
145 return true;
146 return !static_cast<SymbolImpl*>(identifier)->isPrivate();
147 }
148 return includeStringProperties();
149}
150
151ALWAYS_INLINE bool PropertyNameArray::includeSymbolProperties() const
152{
153 return static_cast<std::underlying_type<PropertyNameMode>::type>(m_propertyNameMode) & static_cast<std::underlying_type<PropertyNameMode>::type>(PropertyNameMode::Symbols);
154}
155
156ALWAYS_INLINE bool PropertyNameArray::includeStringProperties() const
157{
158 return static_cast<std::underlying_type<PropertyNameMode>::type>(m_propertyNameMode) & static_cast<std::underlying_type<PropertyNameMode>::type>(PropertyNameMode::Strings);
159}
160
161} // namespace JSC
162