summaryrefslogtreecommitdiffstats
path: root/xpcom
diff options
context:
space:
mode:
Diffstat (limited to 'xpcom')
-rw-r--r--xpcom/ds/nsAtomTable.cpp58
-rw-r--r--xpcom/ds/nsIAtom.idl15
2 files changed, 62 insertions, 11 deletions
diff --git a/xpcom/ds/nsAtomTable.cpp b/xpcom/ds/nsAtomTable.cpp
index 3dd3bd36c..c2e77e31f 100644
--- a/xpcom/ds/nsAtomTable.cpp
+++ b/xpcom/ds/nsAtomTable.cpp
@@ -325,13 +325,7 @@ AtomTableMatchKey(const PLDHashEntryHdr* aEntry, const void* aKey)
nsDependentAtomString(he->mAtom)) == 0;
}
- uint32_t length = he->mAtom->GetLength();
- if (length != k->mLength) {
- return false;
- }
-
- return memcmp(he->mAtom->GetUTF16String(),
- k->mUTF16String, length * sizeof(char16_t)) == 0;
+ return he->mAtom->Equals(k->mUTF16String, k->mLength);
}
static void
@@ -364,17 +358,29 @@ static const PLDHashTableOps AtomTableOps = {
//----------------------------------------------------------------------
+#define RECENTLY_USED_MAIN_THREAD_ATOM_CACHE_SIZE 31
+static nsIAtom*
+ sRecentlyUsedMainThreadAtoms[RECENTLY_USED_MAIN_THREAD_ATOM_CACHE_SIZE] = {};
+
void
DynamicAtom::GCAtomTable()
{
- MutexAutoLock lock(*gAtomTableLock);
- GCAtomTableLocked(lock, GCKind::RegularOperation);
+ if (NS_IsMainThread()) {
+ MutexAutoLock lock(*gAtomTableLock);
+ GCAtomTableLocked(lock, GCKind::RegularOperation);
+ }
}
void
DynamicAtom::GCAtomTableLocked(const MutexAutoLock& aProofOfLock,
GCKind aKind)
{
+
+ MOZ_ASSERT(NS_IsMainThread());
+ for (uint32_t i = 0; i < RECENTLY_USED_MAIN_THREAD_ATOM_CACHE_SIZE; ++i) {
+ sRecentlyUsedMainThreadAtoms[i] = nullptr;
+ }
+
uint32_t removedCount = 0; // Use a non-atomic temporary for cheaper increments.
nsAutoCString nonZeroRefcountAtoms;
uint32_t nonZeroRefcountAtomsCount = 0;
@@ -712,6 +718,40 @@ NS_Atomize(const nsAString& aUTF16String)
return atom.forget();
}
+already_AddRefed<nsIAtom>
+NS_AtomizeMainThread(const nsAString& aUTF16String)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ nsCOMPtr<nsIAtom> retVal;
+ uint32_t hash;
+ AtomTableKey key(aUTF16String.Data(), aUTF16String.Length(), &hash);
+ uint32_t index = hash % RECENTLY_USED_MAIN_THREAD_ATOM_CACHE_SIZE;
+ nsIAtom* atom =
+ sRecentlyUsedMainThreadAtoms[index];
+ if (atom) {
+ uint32_t length = atom->GetLength();
+ if (length == key.mLength &&
+ (memcmp(atom->GetUTF16String(),
+ key.mUTF16String, length * sizeof(char16_t)) == 0)) {
+ retVal = atom;
+ return retVal.forget();
+ }
+ }
+
+ MutexAutoLock lock(*gAtomTableLock);
+ AtomTableEntry* he = static_cast<AtomTableEntry*>(gAtomTable->Add(&key));
+
+ if (he->mAtom) {
+ retVal = he->mAtom;
+ } else {
+ retVal = DynamicAtom::Create(aUTF16String, hash);
+ he->mAtom = retVal;
+ }
+
+ sRecentlyUsedMainThreadAtoms[index] = retVal;
+ return retVal.forget();
+}
+
nsrefcnt
NS_GetNumberOfAtoms(void)
{
diff --git a/xpcom/ds/nsIAtom.idl b/xpcom/ds/nsIAtom.idl
index c02540838..ce4cff485 100644
--- a/xpcom/ds/nsIAtom.idl
+++ b/xpcom/ds/nsIAtom.idl
@@ -37,9 +37,15 @@ interface nsIAtom : nsISupports
size_t SizeOfIncludingThis(in MallocSizeOf aMallocSizeOf);
%{C++
- // note this is NOT virtual so this won't muck with the vtable!
+ // note these are NOT virtual so they won't muck with the vtable!
+ inline bool Equals(char16ptr_t aString, uint32_t aLength) const
+ {
+ return mLength == aLength &&
+ memcmp(mString, aString, mLength * sizeof(char16_t)) == 0;
+ }
+
inline bool Equals(const nsAString& aString) const {
- return aString.Equals(nsDependentString(mString, mLength));
+ return Equals(aString.BeginReading(), aString.Length());
}
inline bool IsStaticAtom() const {
@@ -120,6 +126,11 @@ extern already_AddRefed<nsIAtom> NS_Atomize(const char16_t* aUTF16String);
extern already_AddRefed<nsIAtom> NS_Atomize(const nsAString& aUTF16String);
/**
+ * An optimized version of the method above for the main thread.
+ */
+extern already_AddRefed<nsIAtom> NS_AtomizeMainThread(const nsAString& aUTF16String);
+
+/**
* Return a count of the total number of atoms currently
* alive in the system.
*/