1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/base/FramePropertyTable.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,245 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- 1.5 + * This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "FramePropertyTable.h" 1.10 + 1.11 +#include "mozilla/MemoryReporting.h" 1.12 + 1.13 +namespace mozilla { 1.14 + 1.15 +void 1.16 +FramePropertyTable::Set(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty, 1.17 + void* aValue) 1.18 +{ 1.19 + NS_ASSERTION(aFrame, "Null frame?"); 1.20 + NS_ASSERTION(aProperty, "Null property?"); 1.21 + 1.22 + if (mLastFrame != aFrame || !mLastEntry) { 1.23 + mLastFrame = aFrame; 1.24 + mLastEntry = mEntries.PutEntry(aFrame); 1.25 + } 1.26 + Entry* entry = mLastEntry; 1.27 + 1.28 + if (!entry->mProp.IsArray()) { 1.29 + if (!entry->mProp.mProperty) { 1.30 + // Empty entry, so we can just store our property in the empty slot 1.31 + entry->mProp.mProperty = aProperty; 1.32 + entry->mProp.mValue = aValue; 1.33 + return; 1.34 + } 1.35 + if (entry->mProp.mProperty == aProperty) { 1.36 + // Just overwrite the current value 1.37 + entry->mProp.DestroyValueFor(aFrame); 1.38 + entry->mProp.mValue = aValue; 1.39 + return; 1.40 + } 1.41 + 1.42 + // We need to expand the single current entry to an array 1.43 + PropertyValue current = entry->mProp; 1.44 + entry->mProp.mProperty = nullptr; 1.45 + static_assert(sizeof(nsTArray<PropertyValue>) <= sizeof(void *), 1.46 + "Property array must fit entirely within entry->mProp.mValue"); 1.47 + new (&entry->mProp.mValue) nsTArray<PropertyValue>(4); 1.48 + entry->mProp.ToArray()->AppendElement(current); 1.49 + } 1.50 + 1.51 + nsTArray<PropertyValue>* array = entry->mProp.ToArray(); 1.52 + nsTArray<PropertyValue>::index_type index = 1.53 + array->IndexOf(aProperty, 0, PropertyComparator()); 1.54 + if (index != nsTArray<PropertyValue>::NoIndex) { 1.55 + PropertyValue* pv = &array->ElementAt(index); 1.56 + pv->DestroyValueFor(aFrame); 1.57 + pv->mValue = aValue; 1.58 + return; 1.59 + } 1.60 + 1.61 + array->AppendElement(PropertyValue(aProperty, aValue)); 1.62 +} 1.63 + 1.64 +void* 1.65 +FramePropertyTable::Get(const nsIFrame* aFrame, 1.66 + const FramePropertyDescriptor* aProperty, 1.67 + bool* aFoundResult) 1.68 +{ 1.69 + NS_ASSERTION(aFrame, "Null frame?"); 1.70 + NS_ASSERTION(aProperty, "Null property?"); 1.71 + 1.72 + if (aFoundResult) { 1.73 + *aFoundResult = false; 1.74 + } 1.75 + 1.76 + if (mLastFrame != aFrame) { 1.77 + mLastFrame = const_cast<nsIFrame*>(aFrame); 1.78 + mLastEntry = mEntries.GetEntry(mLastFrame); 1.79 + } 1.80 + Entry* entry = mLastEntry; 1.81 + if (!entry) 1.82 + return nullptr; 1.83 + 1.84 + if (entry->mProp.mProperty == aProperty) { 1.85 + if (aFoundResult) { 1.86 + *aFoundResult = true; 1.87 + } 1.88 + return entry->mProp.mValue; 1.89 + } 1.90 + if (!entry->mProp.IsArray()) { 1.91 + // There's just one property and it's not the one we want, bail 1.92 + return nullptr; 1.93 + } 1.94 + 1.95 + nsTArray<PropertyValue>* array = entry->mProp.ToArray(); 1.96 + nsTArray<PropertyValue>::index_type index = 1.97 + array->IndexOf(aProperty, 0, PropertyComparator()); 1.98 + if (index == nsTArray<PropertyValue>::NoIndex) 1.99 + return nullptr; 1.100 + 1.101 + if (aFoundResult) { 1.102 + *aFoundResult = true; 1.103 + } 1.104 + 1.105 + return array->ElementAt(index).mValue; 1.106 +} 1.107 + 1.108 +void* 1.109 +FramePropertyTable::Remove(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty, 1.110 + bool* aFoundResult) 1.111 +{ 1.112 + NS_ASSERTION(aFrame, "Null frame?"); 1.113 + NS_ASSERTION(aProperty, "Null property?"); 1.114 + 1.115 + if (aFoundResult) { 1.116 + *aFoundResult = false; 1.117 + } 1.118 + 1.119 + if (mLastFrame != aFrame) { 1.120 + mLastFrame = aFrame; 1.121 + mLastEntry = mEntries.GetEntry(aFrame); 1.122 + } 1.123 + Entry* entry = mLastEntry; 1.124 + if (!entry) 1.125 + return nullptr; 1.126 + 1.127 + if (entry->mProp.mProperty == aProperty) { 1.128 + // There's only one entry and it's the one we want 1.129 + void* value = entry->mProp.mValue; 1.130 + mEntries.RawRemoveEntry(entry); 1.131 + mLastEntry = nullptr; 1.132 + if (aFoundResult) { 1.133 + *aFoundResult = true; 1.134 + } 1.135 + return value; 1.136 + } 1.137 + if (!entry->mProp.IsArray()) { 1.138 + // There's just one property and it's not the one we want, bail 1.139 + return nullptr; 1.140 + } 1.141 + 1.142 + nsTArray<PropertyValue>* array = entry->mProp.ToArray(); 1.143 + nsTArray<PropertyValue>::index_type index = 1.144 + array->IndexOf(aProperty, 0, PropertyComparator()); 1.145 + if (index == nsTArray<PropertyValue>::NoIndex) { 1.146 + // No such property, bail 1.147 + return nullptr; 1.148 + } 1.149 + 1.150 + if (aFoundResult) { 1.151 + *aFoundResult = true; 1.152 + } 1.153 + 1.154 + void* result = array->ElementAt(index).mValue; 1.155 + 1.156 + uint32_t last = array->Length() - 1; 1.157 + array->ElementAt(index) = array->ElementAt(last); 1.158 + array->RemoveElementAt(last); 1.159 + 1.160 + if (last == 1) { 1.161 + PropertyValue pv = array->ElementAt(0); 1.162 + array->~nsTArray<PropertyValue>(); 1.163 + entry->mProp = pv; 1.164 + } 1.165 + 1.166 + return result; 1.167 +} 1.168 + 1.169 +void 1.170 +FramePropertyTable::Delete(nsIFrame* aFrame, const FramePropertyDescriptor* aProperty) 1.171 +{ 1.172 + NS_ASSERTION(aFrame, "Null frame?"); 1.173 + NS_ASSERTION(aProperty, "Null property?"); 1.174 + 1.175 + bool found; 1.176 + void* v = Remove(aFrame, aProperty, &found); 1.177 + if (found) { 1.178 + PropertyValue pv(aProperty, v); 1.179 + pv.DestroyValueFor(aFrame); 1.180 + } 1.181 +} 1.182 + 1.183 +/* static */ void 1.184 +FramePropertyTable::DeleteAllForEntry(Entry* aEntry) 1.185 +{ 1.186 + if (!aEntry->mProp.IsArray()) { 1.187 + aEntry->mProp.DestroyValueFor(aEntry->GetKey()); 1.188 + return; 1.189 + } 1.190 + 1.191 + nsTArray<PropertyValue>* array = aEntry->mProp.ToArray(); 1.192 + for (uint32_t i = 0; i < array->Length(); ++i) { 1.193 + array->ElementAt(i).DestroyValueFor(aEntry->GetKey()); 1.194 + } 1.195 + array->~nsTArray<PropertyValue>(); 1.196 +} 1.197 + 1.198 +void 1.199 +FramePropertyTable::DeleteAllFor(nsIFrame* aFrame) 1.200 +{ 1.201 + NS_ASSERTION(aFrame, "Null frame?"); 1.202 + 1.203 + Entry* entry = mEntries.GetEntry(aFrame); 1.204 + if (!entry) 1.205 + return; 1.206 + 1.207 + if (mLastFrame == aFrame) { 1.208 + // Flush cache. We assume DeleteAllForEntry will be called before 1.209 + // a frame is destroyed. 1.210 + mLastFrame = nullptr; 1.211 + mLastEntry = nullptr; 1.212 + } 1.213 + 1.214 + DeleteAllForEntry(entry); 1.215 + mEntries.RawRemoveEntry(entry); 1.216 +} 1.217 + 1.218 +/* static */ PLDHashOperator 1.219 +FramePropertyTable::DeleteEnumerator(Entry* aEntry, void* aArg) 1.220 +{ 1.221 + DeleteAllForEntry(aEntry); 1.222 + return PL_DHASH_REMOVE; 1.223 +} 1.224 + 1.225 +void 1.226 +FramePropertyTable::DeleteAll() 1.227 +{ 1.228 + mLastFrame = nullptr; 1.229 + mLastEntry = nullptr; 1.230 + 1.231 + mEntries.EnumerateEntries(DeleteEnumerator, nullptr); 1.232 +} 1.233 + 1.234 +size_t 1.235 +FramePropertyTable::SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const 1.236 +{ 1.237 + return mEntries.SizeOfExcludingThis(SizeOfPropertyTableEntryExcludingThis, 1.238 + aMallocSizeOf); 1.239 +} 1.240 + 1.241 +/* static */ size_t 1.242 +FramePropertyTable::SizeOfPropertyTableEntryExcludingThis(Entry* aEntry, 1.243 + mozilla::MallocSizeOf aMallocSizeOf, void *) 1.244 +{ 1.245 + return aEntry->mProp.SizeOfExcludingThis(aMallocSizeOf); 1.246 +} 1.247 + 1.248 +}