Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1928)

Side by Side Diff: base/pickle.cc

Issue 1249643007: Align base::Pickle allocations to 4k boundaries (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@accounting_fix
Patch Set: Nits test Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/pickle.h" 5 #include "base/pickle.h"
6 6
7 #include <stdlib.h> 7 #include <stdlib.h>
8 8
9 #include <algorithm> // for max() 9 #include <algorithm> // for max()
10 10
11 #include "base/bits.h"
12 #include "base/macros.h"
13
11 namespace base { 14 namespace base {
12 15
13 // static 16 // static
14 const int Pickle::kPayloadUnit = 64; 17 const int Pickle::kPayloadUnit = 64;
15 18
16 static const size_t kCapacityReadOnly = static_cast<size_t>(-1); 19 static const size_t kCapacityReadOnly = static_cast<size_t>(-1);
17 20
18 PickleIterator::PickleIterator(const Pickle& pickle) 21 PickleIterator::PickleIterator(const Pickle& pickle)
19 : payload_(pickle.payload()), 22 : payload_(pickle.payload()),
20 read_index_(0), 23 read_index_(0),
21 end_index_(pickle.payload_size()) { 24 end_index_(pickle.payload_size()) {
22 } 25 }
23 26
24 template <typename Type> 27 template <typename Type>
25 inline bool PickleIterator::ReadBuiltinType(Type* result) { 28 inline bool PickleIterator::ReadBuiltinType(Type* result) {
26 const char* read_from = GetReadPointerAndAdvance<Type>(); 29 const char* read_from = GetReadPointerAndAdvance<Type>();
27 if (!read_from) 30 if (!read_from)
28 return false; 31 return false;
29 if (sizeof(Type) > sizeof(uint32)) 32 if (sizeof(Type) > sizeof(uint32))
30 memcpy(result, read_from, sizeof(*result)); 33 memcpy(result, read_from, sizeof(*result));
31 else 34 else
32 *result = *reinterpret_cast<const Type*>(read_from); 35 *result = *reinterpret_cast<const Type*>(read_from);
33 return true; 36 return true;
34 } 37 }
35 38
36 inline void PickleIterator::Advance(size_t size) { 39 inline void PickleIterator::Advance(size_t size) {
37 size_t aligned_size = AlignInt(size, sizeof(uint32_t)); 40 size_t aligned_size = bits::Align(size, sizeof(uint32_t));
38 if (end_index_ - read_index_ < aligned_size) { 41 if (end_index_ - read_index_ < aligned_size) {
39 read_index_ = end_index_; 42 read_index_ = end_index_;
40 } else { 43 } else {
41 read_index_ += aligned_size; 44 read_index_ += aligned_size;
42 } 45 }
43 } 46 }
44 47
45 template<typename Type> 48 template<typename Type>
46 inline const char* PickleIterator::GetReadPointerAndAdvance() { 49 inline const char* PickleIterator::GetReadPointerAndAdvance() {
47 if (sizeof(Type) > end_index_ - read_index_) { 50 if (sizeof(Type) > end_index_ - read_index_) {
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after
203 return true; 206 return true;
204 } 207 }
205 208
206 // Payload is uint32 aligned. 209 // Payload is uint32 aligned.
207 210
208 Pickle::Pickle() 211 Pickle::Pickle()
209 : header_(NULL), 212 : header_(NULL),
210 header_size_(sizeof(Header)), 213 header_size_(sizeof(Header)),
211 capacity_after_header_(0), 214 capacity_after_header_(0),
212 write_offset_(0) { 215 write_offset_(0) {
216 static_assert((Pickle::kPayloadUnit & (Pickle::kPayloadUnit - 1)) == 0,
217 "Pickle::kPayloadUnit must be a power of two");
213 Resize(kPayloadUnit); 218 Resize(kPayloadUnit);
214 header_->payload_size = 0; 219 header_->payload_size = 0;
215 } 220 }
216 221
217 Pickle::Pickle(int header_size) 222 Pickle::Pickle(int header_size)
218 : header_(NULL), 223 : header_(NULL),
219 header_size_(AlignInt(header_size, sizeof(uint32))), 224 header_size_(bits::Align(header_size, sizeof(uint32))),
220 capacity_after_header_(0), 225 capacity_after_header_(0),
221 write_offset_(0) { 226 write_offset_(0) {
222 DCHECK_GE(static_cast<size_t>(header_size), sizeof(Header)); 227 DCHECK_GE(static_cast<size_t>(header_size), sizeof(Header));
223 DCHECK_LE(header_size, kPayloadUnit); 228 DCHECK_LE(header_size, kPayloadUnit);
224 Resize(kPayloadUnit); 229 Resize(kPayloadUnit);
225 header_->payload_size = 0; 230 header_->payload_size = 0;
226 } 231 }
227 232
228 Pickle::Pickle(const char* data, int data_len) 233 Pickle::Pickle(const char* data, int data_len)
229 : header_(reinterpret_cast<Header*>(const_cast<char*>(data))), 234 : header_(reinterpret_cast<Header*>(const_cast<char*>(data))),
230 header_size_(0), 235 header_size_(0),
231 capacity_after_header_(kCapacityReadOnly), 236 capacity_after_header_(kCapacityReadOnly),
232 write_offset_(0) { 237 write_offset_(0) {
233 if (data_len >= static_cast<int>(sizeof(Header))) 238 if (data_len >= static_cast<int>(sizeof(Header)))
234 header_size_ = data_len - header_->payload_size; 239 header_size_ = data_len - header_->payload_size;
235 240
236 if (header_size_ > static_cast<unsigned int>(data_len)) 241 if (header_size_ > static_cast<unsigned int>(data_len))
237 header_size_ = 0; 242 header_size_ = 0;
238 243
239 if (header_size_ != AlignInt(header_size_, sizeof(uint32))) 244 if (header_size_ != bits::Align(header_size_, sizeof(uint32)))
240 header_size_ = 0; 245 header_size_ = 0;
241 246
242 // If there is anything wrong with the data, we're not going to use it. 247 // If there is anything wrong with the data, we're not going to use it.
243 if (!header_size_) 248 if (!header_size_)
244 header_ = NULL; 249 header_ = NULL;
245 } 250 }
246 251
247 Pickle::Pickle(const Pickle& other) 252 Pickle::Pickle(const Pickle& other)
248 : header_(NULL), 253 : header_(NULL),
249 header_size_(other.header_size_), 254 header_size_(other.header_size_),
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 bool Pickle::WriteData(const char* data, int length) { 303 bool Pickle::WriteData(const char* data, int length) {
299 return length >= 0 && WriteInt(length) && WriteBytes(data, length); 304 return length >= 0 && WriteInt(length) && WriteBytes(data, length);
300 } 305 }
301 306
302 bool Pickle::WriteBytes(const void* data, int length) { 307 bool Pickle::WriteBytes(const void* data, int length) {
303 WriteBytesCommon(data, length); 308 WriteBytesCommon(data, length);
304 return true; 309 return true;
305 } 310 }
306 311
307 void Pickle::Reserve(size_t length) { 312 void Pickle::Reserve(size_t length) {
308 size_t data_len = AlignInt(length, sizeof(uint32)); 313 size_t data_len = bits::Align(length, sizeof(uint32));
309 DCHECK_GE(data_len, length); 314 DCHECK_GE(data_len, length);
310 #ifdef ARCH_CPU_64_BITS 315 #ifdef ARCH_CPU_64_BITS
311 DCHECK_LE(data_len, kuint32max); 316 DCHECK_LE(data_len, kuint32max);
312 #endif 317 #endif
313 DCHECK_LE(write_offset_, kuint32max - data_len); 318 DCHECK_LE(write_offset_, kuint32max - data_len);
314 size_t new_size = write_offset_ + data_len; 319 size_t new_size = write_offset_ + data_len;
315 if (new_size > capacity_after_header_) 320 if (new_size > capacity_after_header_)
316 Resize(capacity_after_header_ * 2 + new_size); 321 Resize(capacity_after_header_ * 2 + new_size);
317 } 322 }
318 323
319 void Pickle::Resize(size_t new_capacity) { 324 void Pickle::Resize(size_t new_capacity) {
320 CHECK_NE(capacity_after_header_, kCapacityReadOnly); 325 CHECK_NE(capacity_after_header_, kCapacityReadOnly);
321 capacity_after_header_ = AlignInt(new_capacity, kPayloadUnit); 326 capacity_after_header_ = bits::Align(new_capacity, kPayloadUnit);
322 void* p = realloc(header_, GetTotalAllocatedSize()); 327 void* p = realloc(header_, GetTotalAllocatedSize());
323 CHECK(p); 328 CHECK(p);
324 header_ = reinterpret_cast<Header*>(p); 329 header_ = reinterpret_cast<Header*>(p);
325 } 330 }
326 331
327 size_t Pickle::GetTotalAllocatedSize() const { 332 size_t Pickle::GetTotalAllocatedSize() const {
328 if (capacity_after_header_ == kCapacityReadOnly) 333 if (capacity_after_header_ == kCapacityReadOnly)
329 return 0; 334 return 0;
330 return header_size_ + capacity_after_header_; 335 return header_size_ + capacity_after_header_;
331 } 336 }
332 337
333 // static 338 // static
334 const char* Pickle::FindNext(size_t header_size, 339 const char* Pickle::FindNext(size_t header_size,
335 const char* start, 340 const char* start,
336 const char* end) { 341 const char* end) {
337 DCHECK_EQ(header_size, AlignInt(header_size, sizeof(uint32))); 342 DCHECK_EQ(header_size, bits::Align(header_size, sizeof(uint32)));
338 DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit)); 343 DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit));
339 344
340 size_t length = static_cast<size_t>(end - start); 345 size_t length = static_cast<size_t>(end - start);
341 if (length < sizeof(Header)) 346 if (length < sizeof(Header))
342 return NULL; 347 return NULL;
343 348
344 const Header* hdr = reinterpret_cast<const Header*>(start); 349 const Header* hdr = reinterpret_cast<const Header*>(start);
345 if (length < header_size || length - header_size < hdr->payload_size) 350 if (length < header_size || length - header_size < hdr->payload_size)
346 return NULL; 351 return NULL;
347 return start + header_size + hdr->payload_size; 352 return start + header_size + hdr->payload_size;
348 } 353 }
349 354
350 template <size_t length> void Pickle::WriteBytesStatic(const void* data) { 355 template <size_t length> void Pickle::WriteBytesStatic(const void* data) {
351 WriteBytesCommon(data, length); 356 WriteBytesCommon(data, length);
352 } 357 }
353 358
354 template void Pickle::WriteBytesStatic<2>(const void* data); 359 template void Pickle::WriteBytesStatic<2>(const void* data);
355 template void Pickle::WriteBytesStatic<4>(const void* data); 360 template void Pickle::WriteBytesStatic<4>(const void* data);
356 template void Pickle::WriteBytesStatic<8>(const void* data); 361 template void Pickle::WriteBytesStatic<8>(const void* data);
357 362
358 inline void Pickle::WriteBytesCommon(const void* data, size_t length) { 363 inline void Pickle::WriteBytesCommon(const void* data, size_t length) {
359 DCHECK_NE(kCapacityReadOnly, capacity_after_header_) 364 DCHECK_NE(kCapacityReadOnly, capacity_after_header_)
360 << "oops: pickle is readonly"; 365 << "oops: pickle is readonly";
361 MSAN_CHECK_MEM_IS_INITIALIZED(data, length); 366 MSAN_CHECK_MEM_IS_INITIALIZED(data, length);
362 size_t data_len = AlignInt(length, sizeof(uint32)); 367 size_t data_len = bits::Align(length, sizeof(uint32));
363 DCHECK_GE(data_len, length); 368 DCHECK_GE(data_len, length);
364 #ifdef ARCH_CPU_64_BITS 369 #ifdef ARCH_CPU_64_BITS
365 DCHECK_LE(data_len, kuint32max); 370 DCHECK_LE(data_len, kuint32max);
366 #endif 371 #endif
367 DCHECK_LE(write_offset_, kuint32max - data_len); 372 DCHECK_LE(write_offset_, kuint32max - data_len);
368 size_t new_size = write_offset_ + data_len; 373 size_t new_size = write_offset_ + data_len;
369 if (new_size > capacity_after_header_) { 374 if (new_size > capacity_after_header_) {
370 Resize(std::max(capacity_after_header_ * 2, new_size)); 375 size_t new_capacity = capacity_after_header_ * 2;
376 const size_t kPickleHeapAlign = 4096;
377 if (new_capacity > kPickleHeapAlign)
378 new_capacity = bits::Align(new_capacity, kPickleHeapAlign) - kPayloadUnit;
379 Resize(std::max(new_capacity, new_size));
371 } 380 }
372 381
373 char* write = mutable_payload() + write_offset_; 382 char* write = mutable_payload() + write_offset_;
374 memcpy(write, data, length); 383 memcpy(write, data, length);
375 memset(write + length, 0, data_len - length); 384 memset(write + length, 0, data_len - length);
376 header_->payload_size = static_cast<uint32>(new_size); 385 header_->payload_size = static_cast<uint32>(new_size);
377 write_offset_ = new_size; 386 write_offset_ = new_size;
378 } 387 }
379 388
380 } // namespace base 389 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698