Bug 1936278 - Prevent search mode chiclet from being dismissed when clicking in page...
[gecko.git] / dom / ipc / SharedStringMap.cpp
blob648dc9da227204efcaea6a3f61b8f47f22e9e316
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "SharedStringMap.h"
9 #include "MemMapSnapshot.h"
10 #include "ScriptPreloader-inl.h"
12 #include "mozilla/BinarySearch.h"
13 #include "mozilla/Try.h"
15 using namespace mozilla::loader;
17 namespace mozilla {
19 using namespace ipc;
21 namespace dom::ipc {
23 static constexpr uint32_t kSharedStringMapMagic = 0x9e3779b9;
25 static inline size_t GetAlignmentOffset(size_t aOffset, size_t aAlign) {
26 auto mod = aOffset % aAlign;
27 return mod ? aAlign - mod : 0;
30 SharedStringMap::SharedStringMap(const SharedMemoryHandle& aMapHandle,
31 size_t aMapSize) {
32 auto map = MakeRefPtr<SharedMemory>();
34 auto result = map->SetHandle(SharedMemory::CloneHandle(aMapHandle),
35 SharedMemory::OpenRights::RightsReadOnly);
36 MOZ_RELEASE_ASSERT(result);
39 auto result = map->Map(aMapSize);
40 MOZ_RELEASE_ASSERT(result);
43 // We return literal nsStrings and nsCStrings pointing to the mapped data,
44 // which means that we may still have references to the mapped data even
45 // after this instance is destroyed. That means that we need to keep the
46 // mapping alive until process shutdown, in order to be safe.
47 mMappedMemory = map->TakeMapping();
48 mHandle = map->TakeHandle();
50 MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic);
53 SharedStringMap::SharedStringMap(SharedStringMapBuilder&& aBuilder) {
54 RefPtr<SharedMemory> map;
55 auto result = aBuilder.Finalize(map);
56 MOZ_RELEASE_ASSERT(result.isOk() && map);
58 mMappedMemory = map->TakeMapping();
59 mHandle = map->TakeHandle();
61 MOZ_RELEASE_ASSERT(GetHeader().mMagic == kSharedStringMapMagic);
64 mozilla::ipc::SharedMemoryHandle SharedStringMap::CloneHandle() const {
65 return SharedMemory::CloneHandle(mHandle);
68 bool SharedStringMap::Has(const nsCString& aKey) {
69 size_t index;
70 return Find(aKey, &index);
73 bool SharedStringMap::Get(const nsCString& aKey, nsAString& aValue) {
74 const auto& entries = Entries();
76 size_t index;
77 if (!Find(aKey, &index)) {
78 return false;
81 aValue.Assign(ValueTable().Get(entries[index].mValue));
82 return true;
85 bool SharedStringMap::Find(const nsCString& aKey, size_t* aIndex) {
86 const auto& keys = KeyTable();
88 return BinarySearchIf(
89 Entries(), 0, EntryCount(),
90 [&](const Entry& aEntry) { return Compare(aKey, keys.Get(aEntry.mKey)); },
91 aIndex);
94 void SharedStringMapBuilder::Add(const nsCString& aKey,
95 const nsString& aValue) {
96 mEntries.InsertOrUpdate(aKey,
97 Entry{mKeyTable.Add(aKey), mValueTable.Add(aValue)});
100 Result<Ok, nsresult> SharedStringMapBuilder::Finalize(
101 RefPtr<SharedMemory>& aMap) {
102 using Header = SharedStringMap::Header;
104 MOZ_ASSERT(mEntries.Count() == mKeyTable.Count());
106 auto keys = ToTArray<nsTArray<nsCString>>(mEntries.Keys());
107 keys.Sort();
109 Header header = {kSharedStringMapMagic, uint32_t(keys.Length())};
111 size_t offset = sizeof(header);
112 offset += GetAlignmentOffset(offset, alignof(Header));
114 offset += keys.Length() * sizeof(SharedStringMap::Entry);
116 header.mKeyStringsOffset = offset;
117 header.mKeyStringsSize = mKeyTable.Size();
119 offset += header.mKeyStringsSize;
120 offset +=
121 GetAlignmentOffset(offset, alignof(decltype(mValueTable)::ElemType));
123 header.mValueStringsOffset = offset;
124 header.mValueStringsSize = mValueTable.Size();
126 offset += header.mValueStringsSize;
128 MemMapSnapshot mem;
129 MOZ_TRY(mem.Init(offset));
131 auto headerPtr = mem.Get<Header>();
132 headerPtr[0] = header;
134 auto* entry = reinterpret_cast<Entry*>(&headerPtr[1]);
135 for (auto& key : keys) {
136 *entry++ = mEntries.Get(key);
139 auto ptr = mem.Get<uint8_t>();
141 mKeyTable.Write({&ptr[header.mKeyStringsOffset], header.mKeyStringsSize});
143 mValueTable.Write(
144 {&ptr[header.mValueStringsOffset], header.mValueStringsSize});
146 mKeyTable.Clear();
147 mValueTable.Clear();
148 mEntries.Clear();
150 return mem.Finalize(aMap);
153 } // namespace dom::ipc
154 } // namespace mozilla