Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
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/. */
7 #include "ds/LifoAlloc.h"
9 #include "mozilla/MathAlgorithms.h"
11 using namespace js;
13 using mozilla::RoundUpPow2;
14 using mozilla::tl::BitSize;
16 namespace js {
17 namespace detail {
19 BumpChunk *
20 BumpChunk::new_(size_t chunkSize)
21 {
22 JS_ASSERT(RoundUpPow2(chunkSize) == chunkSize);
23 void *mem = js_malloc(chunkSize);
24 if (!mem)
25 return nullptr;
26 BumpChunk *result = new (mem) BumpChunk(chunkSize - sizeof(BumpChunk));
28 // We assume that the alignment of sAlign is less than that of
29 // the underlying memory allocator -- creating a new BumpChunk should
30 // always satisfy the sAlign alignment constraint.
31 JS_ASSERT(AlignPtr(result->bump) == result->bump);
32 return result;
33 }
35 void
36 BumpChunk::delete_(BumpChunk *chunk)
37 {
38 #ifdef DEBUG
39 // Part of the chunk may have been marked as poisoned/noaccess. Undo that
40 // before writing the 0xcd bytes.
41 size_t size = sizeof(*chunk) + chunk->bumpSpaceSize;
42 MOZ_MAKE_MEM_UNDEFINED(chunk, size);
43 memset(chunk, 0xcd, size);
44 #endif
45 js_free(chunk);
46 }
48 bool
49 BumpChunk::canAlloc(size_t n)
50 {
51 char *aligned = AlignPtr(bump);
52 char *bumped = aligned + n;
53 return bumped <= limit && bumped > headerBase();
54 }
56 } // namespace detail
57 } // namespace js
59 void
60 LifoAlloc::freeAll()
61 {
62 while (first) {
63 BumpChunk *victim = first;
64 first = first->next();
65 decrementCurSize(victim->computedSizeOfIncludingThis());
66 BumpChunk::delete_(victim);
67 }
68 first = latest = last = nullptr;
70 // Nb: maintaining curSize_ correctly isn't easy. Fortunately, this is an
71 // excellent sanity check.
72 JS_ASSERT(curSize_ == 0);
73 }
75 LifoAlloc::BumpChunk *
76 LifoAlloc::getOrCreateChunk(size_t n)
77 {
78 if (first) {
79 // Look for existing, unused BumpChunks to satisfy the request.
80 while (latest->next()) {
81 latest = latest->next();
82 latest->resetBump(); // This was an unused BumpChunk on the chain.
83 if (latest->canAlloc(n))
84 return latest;
85 }
86 }
88 size_t defaultChunkFreeSpace = defaultChunkSize_ - sizeof(BumpChunk);
89 size_t chunkSize;
90 if (n > defaultChunkFreeSpace) {
91 size_t allocSizeWithHeader = n + sizeof(BumpChunk);
93 // Guard for overflow.
94 if (allocSizeWithHeader < n ||
95 (allocSizeWithHeader & (size_t(1) << (BitSize<size_t>::value - 1)))) {
96 return nullptr;
97 }
99 chunkSize = RoundUpPow2(allocSizeWithHeader);
100 } else {
101 chunkSize = defaultChunkSize_;
102 }
104 // If we get here, we couldn't find an existing BumpChunk to fill the request.
105 BumpChunk *newChunk = BumpChunk::new_(chunkSize);
106 if (!newChunk)
107 return nullptr;
108 if (!first) {
109 latest = first = last = newChunk;
110 } else {
111 JS_ASSERT(latest && !latest->next());
112 latest->setNext(newChunk);
113 latest = last = newChunk;
114 }
116 size_t computedChunkSize = newChunk->computedSizeOfIncludingThis();
117 JS_ASSERT(computedChunkSize == chunkSize);
118 incrementCurSize(computedChunkSize);
120 return newChunk;
121 }
123 void
124 LifoAlloc::transferFrom(LifoAlloc *other)
125 {
126 JS_ASSERT(!markCount);
127 JS_ASSERT(!other->markCount);
129 if (!other->first)
130 return;
132 incrementCurSize(other->curSize_);
133 if (other->isEmpty())
134 appendUnused(other->first, other->last);
135 else
136 appendUsed(other->first, other->latest, other->last);
137 other->first = other->last = other->latest = nullptr;
138 other->curSize_ = 0;
139 }
141 void
142 LifoAlloc::transferUnusedFrom(LifoAlloc *other)
143 {
144 JS_ASSERT(!markCount);
145 JS_ASSERT(latest == first);
147 if (other->markCount || !other->first)
148 return;
150 // Transfer all chunks *after* |latest|.
152 if (other->latest->next()) {
153 if (other->latest == other->first) {
154 // We're transferring everything except the first chunk.
155 size_t delta = other->curSize_ - other->first->computedSizeOfIncludingThis();
156 other->decrementCurSize(delta);
157 incrementCurSize(delta);
158 } else {
159 for (BumpChunk *chunk = other->latest->next(); chunk; chunk = chunk->next()) {
160 size_t size = chunk->computedSizeOfIncludingThis();
161 incrementCurSize(size);
162 other->decrementCurSize(size);
163 }
164 }
166 appendUnused(other->latest->next(), other->last);
167 other->latest->setNext(nullptr);
168 other->last = other->latest;
169 }
170 }