Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/ipc/SharedStringMap.cpp
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* vim: set ts=8 sts=4 et sw=4 tw=99: */
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/. */
6
7
#include "SharedStringMap.h"
8
9
#include "MemMapSnapshot.h"
10
#include "ScriptPreloader-inl.h"
11
12
#include "mozilla/BinarySearch.h"
13
#include "mozilla/ipc/FileDescriptor.h"
14
15
using namespace mozilla::loader;
16
17
namespace mozilla {
18
19
using namespace ipc;
20
21
namespace dom {
22
namespace ipc {
23
24
static inline size_t
25
GetAlignmentOffset(size_t aOffset, size_t aAlign)
26
0
{
27
0
  auto mod = aOffset % aAlign;
28
0
  return mod ? aAlign - mod : 0;
29
0
}
30
31
32
SharedStringMap::SharedStringMap(const FileDescriptor& aMapFile, size_t aMapSize)
33
0
{
34
0
  auto result = mMap.initWithHandle(aMapFile, aMapSize);
35
0
  MOZ_RELEASE_ASSERT(result.isOk());
36
0
  // We return literal nsStrings and nsCStrings pointing to the mapped data,
37
0
  // which means that we may still have references to the mapped data even
38
0
  // after this instance is destroyed. That means that we need to keep the
39
0
  // mapping alive until process shutdown, in order to be safe.
40
0
  mMap.setPersistent();
41
0
}
42
43
SharedStringMap::SharedStringMap(SharedStringMapBuilder&& aBuilder)
44
0
{
45
0
  auto result = aBuilder.Finalize(mMap);
46
0
  MOZ_RELEASE_ASSERT(result.isOk());
47
0
  mMap.setPersistent();
48
0
}
49
50
mozilla::ipc::FileDescriptor
51
SharedStringMap::CloneFileDescriptor() const
52
0
{
53
0
  return mMap.cloneHandle();
54
0
}
55
56
bool
57
SharedStringMap::Has(const nsCString& aKey)
58
0
{
59
0
  size_t index;
60
0
  return Find(aKey, &index);
61
0
}
62
63
bool
64
SharedStringMap::Get(const nsCString& aKey, nsAString& aValue)
65
0
{
66
0
  const auto& entries = Entries();
67
0
68
0
  size_t index;
69
0
  if (!Find(aKey, &index)) {
70
0
    return false;
71
0
  }
72
0
73
0
  aValue.Assign(ValueTable().Get(entries[index].mValue));
74
0
  return true;
75
0
}
76
77
bool
78
SharedStringMap::Find(const nsCString& aKey, size_t* aIndex)
79
0
{
80
0
  const auto& keys = KeyTable();
81
0
82
0
  return BinarySearchIf(Entries(), 0, EntryCount(),
83
0
                        [&] (const Entry& aEntry) {
84
0
                          return aKey.Compare(keys.GetBare(aEntry.mKey));
85
0
                        },
86
0
                        aIndex);
87
0
}
88
89
90
void
91
SharedStringMapBuilder::Add(const nsCString& aKey, const nsString& aValue)
92
0
{
93
0
  mEntries.Put(aKey, {mKeyTable.Add(aKey), mValueTable.Add(aValue)});
94
0
}
95
96
Result<Ok, nsresult>
97
SharedStringMapBuilder::Finalize(loader::AutoMemMap& aMap)
98
0
{
99
0
  using Header = SharedStringMap::Header;
100
0
101
0
  MOZ_ASSERT(mEntries.Count() == mKeyTable.Count());
102
0
103
0
  nsTArray<nsCString> keys(mEntries.Count());
104
0
  for (auto iter = mEntries.Iter(); !iter.Done(); iter.Next()) {
105
0
    keys.AppendElement(iter.Key());
106
0
  }
107
0
  keys.Sort();
108
0
109
0
110
0
  Header header = {uint32_t(keys.Length())};
111
0
112
0
  size_t offset = sizeof(header);
113
0
  offset += GetAlignmentOffset(offset, alignof(Header));
114
0
115
0
  offset += keys.Length() * sizeof(SharedStringMap::Entry);
116
0
117
0
  header.mKeyStringsOffset = offset;
118
0
  header.mKeyStringsSize = mKeyTable.Size();
119
0
120
0
  offset += header.mKeyStringsSize;
121
0
  offset += GetAlignmentOffset(offset, alignof(decltype(mValueTable)::ElemType));
122
0
123
0
  header.mValueStringsOffset = offset;
124
0
  header.mValueStringsSize = mValueTable.Size();
125
0
126
0
  offset += header.mValueStringsSize;
127
0
128
0
129
0
  MemMapSnapshot mem;
130
0
  MOZ_TRY(mem.Init(offset));
131
0
132
0
  auto headerPtr = mem.Get<Header>();
133
0
  headerPtr[0] = header;
134
0
135
0
  auto* entry = reinterpret_cast<Entry*>(&headerPtr[1]);
136
0
  for (auto& key : keys) {
137
0
    *entry++ = mEntries.Get(key);
138
0
  }
139
0
140
0
  auto ptr = mem.Get<uint8_t>();
141
0
142
0
  mKeyTable.Write({ &ptr[header.mKeyStringsOffset],
143
0
                    header.mKeyStringsSize });
144
0
145
0
  mValueTable.Write({ &ptr[header.mValueStringsOffset],
146
0
                      header.mValueStringsSize });
147
0
148
0
  mKeyTable.Clear();
149
0
  mValueTable.Clear();
150
0
  mEntries.Clear();
151
0
152
0
  return mem.Finalize(aMap);
153
0
}
154
155
} // ipc
156
} // dom
157
} // mozilla