layout/base/FramePropertyTable.cpp

changeset 0
6474c204b198
equal deleted inserted replaced
-1:000000000000 0:380375190005
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6 #include "FramePropertyTable.h"
7
8 #include "mozilla/MemoryReporting.h"
9
10 namespace mozilla {
11
12 void
13 FramePropertyTable::Set(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty,
14 void* aValue)
15 {
16 NS_ASSERTION(aFrame, "Null frame?");
17 NS_ASSERTION(aProperty, "Null property?");
18
19 if (mLastFrame != aFrame || !mLastEntry) {
20 mLastFrame = aFrame;
21 mLastEntry = mEntries.PutEntry(aFrame);
22 }
23 Entry* entry = mLastEntry;
24
25 if (!entry->mProp.IsArray()) {
26 if (!entry->mProp.mProperty) {
27 // Empty entry, so we can just store our property in the empty slot
28 entry->mProp.mProperty = aProperty;
29 entry->mProp.mValue = aValue;
30 return;
31 }
32 if (entry->mProp.mProperty == aProperty) {
33 // Just overwrite the current value
34 entry->mProp.DestroyValueFor(aFrame);
35 entry->mProp.mValue = aValue;
36 return;
37 }
38
39 // We need to expand the single current entry to an array
40 PropertyValue current = entry->mProp;
41 entry->mProp.mProperty = nullptr;
42 static_assert(sizeof(nsTArray<PropertyValue>) <= sizeof(void *),
43 "Property array must fit entirely within entry->mProp.mValue");
44 new (&entry->mProp.mValue) nsTArray<PropertyValue>(4);
45 entry->mProp.ToArray()->AppendElement(current);
46 }
47
48 nsTArray<PropertyValue>* array = entry->mProp.ToArray();
49 nsTArray<PropertyValue>::index_type index =
50 array->IndexOf(aProperty, 0, PropertyComparator());
51 if (index != nsTArray<PropertyValue>::NoIndex) {
52 PropertyValue* pv = &array->ElementAt(index);
53 pv->DestroyValueFor(aFrame);
54 pv->mValue = aValue;
55 return;
56 }
57
58 array->AppendElement(PropertyValue(aProperty, aValue));
59 }
60
61 void*
62 FramePropertyTable::Get(const nsIFrame* aFrame,
63 const FramePropertyDescriptor* aProperty,
64 bool* aFoundResult)
65 {
66 NS_ASSERTION(aFrame, "Null frame?");
67 NS_ASSERTION(aProperty, "Null property?");
68
69 if (aFoundResult) {
70 *aFoundResult = false;
71 }
72
73 if (mLastFrame != aFrame) {
74 mLastFrame = const_cast<nsIFrame*>(aFrame);
75 mLastEntry = mEntries.GetEntry(mLastFrame);
76 }
77 Entry* entry = mLastEntry;
78 if (!entry)
79 return nullptr;
80
81 if (entry->mProp.mProperty == aProperty) {
82 if (aFoundResult) {
83 *aFoundResult = true;
84 }
85 return entry->mProp.mValue;
86 }
87 if (!entry->mProp.IsArray()) {
88 // There's just one property and it's not the one we want, bail
89 return nullptr;
90 }
91
92 nsTArray<PropertyValue>* array = entry->mProp.ToArray();
93 nsTArray<PropertyValue>::index_type index =
94 array->IndexOf(aProperty, 0, PropertyComparator());
95 if (index == nsTArray<PropertyValue>::NoIndex)
96 return nullptr;
97
98 if (aFoundResult) {
99 *aFoundResult = true;
100 }
101
102 return array->ElementAt(index).mValue;
103 }
104
105 void*
106 FramePropertyTable::Remove(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty,
107 bool* aFoundResult)
108 {
109 NS_ASSERTION(aFrame, "Null frame?");
110 NS_ASSERTION(aProperty, "Null property?");
111
112 if (aFoundResult) {
113 *aFoundResult = false;
114 }
115
116 if (mLastFrame != aFrame) {
117 mLastFrame = aFrame;
118 mLastEntry = mEntries.GetEntry(aFrame);
119 }
120 Entry* entry = mLastEntry;
121 if (!entry)
122 return nullptr;
123
124 if (entry->mProp.mProperty == aProperty) {
125 // There's only one entry and it's the one we want
126 void* value = entry->mProp.mValue;
127 mEntries.RawRemoveEntry(entry);
128 mLastEntry = nullptr;
129 if (aFoundResult) {
130 *aFoundResult = true;
131 }
132 return value;
133 }
134 if (!entry->mProp.IsArray()) {
135 // There's just one property and it's not the one we want, bail
136 return nullptr;
137 }
138
139 nsTArray<PropertyValue>* array = entry->mProp.ToArray();
140 nsTArray<PropertyValue>::index_type index =
141 array->IndexOf(aProperty, 0, PropertyComparator());
142 if (index == nsTArray<PropertyValue>::NoIndex) {
143 // No such property, bail
144 return nullptr;
145 }
146
147 if (aFoundResult) {
148 *aFoundResult = true;
149 }
150
151 void* result = array->ElementAt(index).mValue;
152
153 uint32_t last = array->Length() - 1;
154 array->ElementAt(index) = array->ElementAt(last);
155 array->RemoveElementAt(last);
156
157 if (last == 1) {
158 PropertyValue pv = array->ElementAt(0);
159 array->~nsTArray<PropertyValue>();
160 entry->mProp = pv;
161 }
162
163 return result;
164 }
165
166 void
167 FramePropertyTable::Delete(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty)
168 {
169 NS_ASSERTION(aFrame, "Null frame?");
170 NS_ASSERTION(aProperty, "Null property?");
171
172 bool found;
173 void* v = Remove(aFrame, aProperty, &found);
174 if (found) {
175 PropertyValue pv(aProperty, v);
176 pv.DestroyValueFor(aFrame);
177 }
178 }
179
180 /* static */ void
181 FramePropertyTable::DeleteAllForEntry(Entry* aEntry)
182 {
183 if (!aEntry->mProp.IsArray()) {
184 aEntry->mProp.DestroyValueFor(aEntry->GetKey());
185 return;
186 }
187
188 nsTArray<PropertyValue>* array = aEntry->mProp.ToArray();
189 for (uint32_t i = 0; i < array->Length(); ++i) {
190 array->ElementAt(i).DestroyValueFor(aEntry->GetKey());
191 }
192 array->~nsTArray<PropertyValue>();
193 }
194
195 void
196 FramePropertyTable::DeleteAllFor(nsIFrame* aFrame)
197 {
198 NS_ASSERTION(aFrame, "Null frame?");
199
200 Entry* entry = mEntries.GetEntry(aFrame);
201 if (!entry)
202 return;
203
204 if (mLastFrame == aFrame) {
205 // Flush cache. We assume DeleteAllForEntry will be called before
206 // a frame is destroyed.
207 mLastFrame = nullptr;
208 mLastEntry = nullptr;
209 }
210
211 DeleteAllForEntry(entry);
212 mEntries.RawRemoveEntry(entry);
213 }
214
215 /* static */ PLDHashOperator
216 FramePropertyTable::DeleteEnumerator(Entry* aEntry, void* aArg)
217 {
218 DeleteAllForEntry(aEntry);
219 return PL_DHASH_REMOVE;
220 }
221
222 void
223 FramePropertyTable::DeleteAll()
224 {
225 mLastFrame = nullptr;
226 mLastEntry = nullptr;
227
228 mEntries.EnumerateEntries(DeleteEnumerator, nullptr);
229 }
230
231 size_t
232 FramePropertyTable::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
233 {
234 return mEntries.SizeOfExcludingThis(SizeOfPropertyTableEntryExcludingThis,
235 aMallocSizeOf);
236 }
237
238 /* static */ size_t
239 FramePropertyTable::SizeOfPropertyTableEntryExcludingThis(Entry* aEntry,
240 mozilla::MallocSizeOf aMallocSizeOf, void *)
241 {
242 return aEntry->mProp.SizeOfExcludingThis(aMallocSizeOf);
243 }
244
245 }

mercurial