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

Unified Diff: third_party/re2/util/arena.cc

Issue 10575037: Include RE2 library (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Less intrusive fix for Android Created 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/re2/util/arena.h ('k') | third_party/re2/util/atomicops.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/re2/util/arena.cc
diff --git a/third_party/re2/util/arena.cc b/third_party/re2/util/arena.cc
new file mode 100644
index 0000000000000000000000000000000000000000..25753c5df5cca24eead3ca9e3f4527797e24b895
--- /dev/null
+++ b/third_party/re2/util/arena.cc
@@ -0,0 +1,168 @@
+// Copyright 2000 The RE2 Authors. All Rights Reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "util/util.h"
+
+namespace re2 {
+
+// ----------------------------------------------------------------------
+// UnsafeArena::UnsafeArena()
+// UnsafeArena::~UnsafeArena()
+// Destroying the arena automatically calls Reset()
+// ----------------------------------------------------------------------
+
+
+UnsafeArena::UnsafeArena(const size_t block_size)
+ : block_size_(block_size),
+ freestart_(NULL), // set for real in Reset()
+ last_alloc_(NULL),
+ remaining_(0),
+ blocks_alloced_(1),
+ overflow_blocks_(NULL) {
+ assert(block_size > kDefaultAlignment);
+
+ first_blocks_[0].mem = reinterpret_cast<char*>(malloc(block_size_));
+ first_blocks_[0].size = block_size_;
+
+ Reset();
+}
+
+UnsafeArena::~UnsafeArena() {
+ FreeBlocks();
+ assert(overflow_blocks_ == NULL); // FreeBlocks() should do that
+ // The first X blocks stay allocated always by default. Delete them now.
+ for (int i = 0; i < blocks_alloced_; i++)
+ free(first_blocks_[i].mem);
+}
+
+// ----------------------------------------------------------------------
+// UnsafeArena::Reset()
+// Clears all the memory an arena is using.
+// ----------------------------------------------------------------------
+
+void UnsafeArena::Reset() {
+ FreeBlocks();
+ freestart_ = first_blocks_[0].mem;
+ remaining_ = first_blocks_[0].size;
+ last_alloc_ = NULL;
+
+ // We do not know for sure whether or not the first block is aligned,
+ // so we fix that right now.
+ const int overage = reinterpret_cast<uintptr_t>(freestart_) &
+ (kDefaultAlignment-1);
+ if (overage > 0) {
+ const int waste = kDefaultAlignment - overage;
+ freestart_ += waste;
+ remaining_ -= waste;
+ }
+ freestart_when_empty_ = freestart_;
+ assert(!(reinterpret_cast<uintptr_t>(freestart_)&(kDefaultAlignment-1)));
+}
+
+// -------------------------------------------------------------
+// UnsafeArena::AllocNewBlock()
+// Adds and returns an AllocatedBlock.
+// The returned AllocatedBlock* is valid until the next call
+// to AllocNewBlock or Reset. (i.e. anything that might
+// affect overflow_blocks_).
+// -------------------------------------------------------------
+
+UnsafeArena::AllocatedBlock* UnsafeArena::AllocNewBlock(const size_t block_size) {
+ AllocatedBlock *block;
+ // Find the next block.
+ if ( blocks_alloced_ < arraysize(first_blocks_) ) {
+ // Use one of the pre-allocated blocks
+ block = &first_blocks_[blocks_alloced_++];
+ } else { // oops, out of space, move to the vector
+ if (overflow_blocks_ == NULL) overflow_blocks_ = new vector<AllocatedBlock>;
+ // Adds another block to the vector.
+ overflow_blocks_->resize(overflow_blocks_->size()+1);
+ // block points to the last block of the vector.
+ block = &overflow_blocks_->back();
+ }
+
+ block->mem = reinterpret_cast<char*>(malloc(block_size));
+ block->size = block_size;
+
+ return block;
+}
+
+// ----------------------------------------------------------------------
+// UnsafeArena::GetMemoryFallback()
+// We take memory out of our pool, aligned on the byte boundary
+// requested. If we don't have space in our current pool, we
+// allocate a new block (wasting the remaining space in the
+// current block) and give you that. If your memory needs are
+// too big for a single block, we make a special your-memory-only
+// allocation -- this is equivalent to not using the arena at all.
+// ----------------------------------------------------------------------
+
+void* UnsafeArena::GetMemoryFallback(const size_t size, const int align) {
+ if (size == 0)
+ return NULL; // stl/stl_alloc.h says this is okay
+
+ assert(align > 0 && 0 == (align & (align - 1))); // must be power of 2
+
+ // If the object is more than a quarter of the block size, allocate
+ // it separately to avoid wasting too much space in leftover bytes
+ if (block_size_ == 0 || size > block_size_/4) {
+ // then it gets its own block in the arena
+ assert(align <= kDefaultAlignment); // because that's what new gives us
+ // This block stays separate from the rest of the world; in particular
+ // we don't update last_alloc_ so you can't reclaim space on this block.
+ return AllocNewBlock(size)->mem;
+ }
+
+ const int overage =
+ (reinterpret_cast<uintptr_t>(freestart_) & (align-1));
+ if (overage) {
+ const int waste = align - overage;
+ freestart_ += waste;
+ if (waste < remaining_) {
+ remaining_ -= waste;
+ } else {
+ remaining_ = 0;
+ }
+ }
+ if (size > remaining_) {
+ AllocatedBlock *block = AllocNewBlock(block_size_);
+ freestart_ = block->mem;
+ remaining_ = block->size;
+ }
+ remaining_ -= size;
+ last_alloc_ = freestart_;
+ freestart_ += size;
+ assert((reinterpret_cast<uintptr_t>(last_alloc_) & (align-1)) == 0);
+ return reinterpret_cast<void*>(last_alloc_);
+}
+
+// ----------------------------------------------------------------------
+// UnsafeArena::FreeBlocks()
+// Unlike GetMemory(), which does actual work, ReturnMemory() is a
+// no-op: we don't "free" memory until Reset() is called. We do
+// update some stats, though. Note we do no checking that the
+// pointer you pass in was actually allocated by us, or that it
+// was allocated for the size you say, so be careful here!
+// FreeBlocks() does the work for Reset(), actually freeing all
+// memory allocated in one fell swoop.
+// ----------------------------------------------------------------------
+
+void UnsafeArena::FreeBlocks() {
+ for ( int i = 1; i < blocks_alloced_; ++i ) { // keep first block alloced
+ free(first_blocks_[i].mem);
+ first_blocks_[i].mem = NULL;
+ first_blocks_[i].size = 0;
+ }
+ blocks_alloced_ = 1;
+ if (overflow_blocks_ != NULL) {
+ vector<AllocatedBlock>::iterator it;
+ for (it = overflow_blocks_->begin(); it != overflow_blocks_->end(); ++it) {
+ free(it->mem);
+ }
+ delete overflow_blocks_; // These should be used very rarely
+ overflow_blocks_ = NULL;
+ }
+}
+
+} // namespace re2
« no previous file with comments | « third_party/re2/util/arena.h ('k') | third_party/re2/util/atomicops.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698