summaryrefslogtreecommitdiffstats
path: root/courgette/encoded_program.cc
diff options
context:
space:
mode:
authortommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-06 17:42:45 +0000
committertommi@chromium.org <tommi@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-06 17:42:45 +0000
commit43a9e24a52fa867db98fc2195b8db85b4729e7a1 (patch)
treecad7a14c415542083ac3d1ecc2df1fd86f789557 /courgette/encoded_program.cc
parent6768ac0b06ae36ec7b2d27adfb9b64fc17f57cee (diff)
downloadchromium_src-43a9e24a52fa867db98fc2195b8db85b4729e7a1.zip
chromium_src-43a9e24a52fa867db98fc2195b8db85b4729e7a1.tar.gz
chromium_src-43a9e24a52fa867db98fc2195b8db85b4729e7a1.tar.bz2
Switch out use of std::string and std::vector for large allocations for a buffer class that doesn't throw exceptions.
The new buffer class is pretty simple and relies on the MemoryAllocator class that I previously to back large allocations with mapped files when memory is scarce. That reduced the number of crashes quite a bit but we still crash on machines that are simply out of diskspace as well. So, the right thing to do is to expect and handle failures which is what this cl is all about. What we should see once this has landed is that crash dumps due to courgette running out of disk space should disappear from crash/ and instead we should see the number of users that run into this particular problem in dashboards. TEST=Courgette out-of-memory/out-of-diskspace errors should disappear from crash/ BUG=74777 Review URL: http://codereview.chromium.org/6677141 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@80648 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'courgette/encoded_program.cc')
-rw-r--r--courgette/encoded_program.cc154
1 files changed, 70 insertions, 84 deletions
diff --git a/courgette/encoded_program.cc b/courgette/encoded_program.cc
index a479a40..a675dc2 100644
--- a/courgette/encoded_program.cc
+++ b/courgette/encoded_program.cc
@@ -33,46 +33,46 @@ const int kStreamOriginAddresses = kStreamMisc;
const int kStreamLimit = 9;
// Constructor is here rather than in the header. Although the constructor
-// appears to do nothing it is fact quite large because of the implict calls to
+// appears to do nothing it is fact quite large because of the implicit calls to
// field constructors. Ditto for the destructor.
EncodedProgram::EncodedProgram() : image_base_(0) {}
EncodedProgram::~EncodedProgram() {}
// Serializes a vector of integral values using Varint32 coding.
-template<typename T, typename A>
-CheckBool WriteVector(const std::vector<T, A>& items, SinkStream* buffer) {
+template<typename V>
+CheckBool WriteVector(const V& items, SinkStream* buffer) {
size_t count = items.size();
bool ok = buffer->WriteSizeVarint32(count);
for (size_t i = 0; ok && i < count; ++i) {
- COMPILE_ASSERT(sizeof(T) <= sizeof(uint32), // NOLINT
+ COMPILE_ASSERT(sizeof(items[0]) <= sizeof(uint32), // NOLINT
T_must_fit_in_uint32);
ok = buffer->WriteSizeVarint32(items[i]);
}
return ok;
}
-template<typename T, typename A>
-bool ReadVector(std::vector<T, A>* items, SourceStream* buffer) {
+template<typename V>
+bool ReadVector(V* items, SourceStream* buffer) {
uint32 count;
if (!buffer->ReadVarint32(&count))
return false;
items->clear();
- items->reserve(count);
- for (size_t i = 0; i < count; ++i) {
+
+ bool ok = items->reserve(count);
+ for (size_t i = 0; ok && i < count; ++i) {
uint32 item;
- if (!buffer->ReadVarint32(&item))
- return false;
- // TODO(tommi): Handle errors.
- items->push_back(static_cast<T>(item));
+ ok = buffer->ReadVarint32(&item);
+ if (ok)
+ ok = items->push_back(static_cast<typename V::value_type>(item));
}
- return true;
+ return ok;
}
// Serializes a vector, using delta coding followed by Varint32 coding.
-template<typename A>
-CheckBool WriteU32Delta(const std::vector<uint32, A>& set, SinkStream* buffer) {
+template<typename V>
+CheckBool WriteU32Delta(const V& set, SinkStream* buffer) {
size_t count = set.size();
bool ok = buffer->WriteSizeVarint32(count);
uint32 prev = 0;
@@ -85,65 +85,61 @@ CheckBool WriteU32Delta(const std::vector<uint32, A>& set, SinkStream* buffer) {
return ok;
}
-template <typename A>
-static CheckBool ReadU32Delta(std::vector<uint32, A>* set,
- SourceStream* buffer) {
+template <typename V>
+static CheckBool ReadU32Delta(V* set, SourceStream* buffer) {
uint32 count;
if (!buffer->ReadVarint32(&count))
return false;
set->clear();
- // TODO(tommi): Handle errors.
- set->reserve(count);
+ bool ok = set->reserve(count);
uint32 prev = 0;
- for (size_t i = 0; i < count; ++i) {
+ for (size_t i = 0; ok && i < count; ++i) {
uint32 delta;
- if (!buffer->ReadVarint32(&delta))
- return false;
- uint32 current = prev + delta;
- // TODO(tommi): handle errors
- set->push_back(current);
- prev = current;
+ ok = buffer->ReadVarint32(&delta);
+ if (ok) {
+ uint32 current = prev + delta;
+ ok = set->push_back(current);
+ prev = current;
+ }
}
- // TODO(tommi): Handle errors.
- return true;
+ return ok;
}
// Write a vector as the byte representation of the contents.
//
// (This only really makes sense for a type T that has sizeof(T)==1, otherwise
-// serialized representation is not endian-agnositic. But it is useful to keep
+// serialized representation is not endian-agnostic. But it is useful to keep
// the possibility of a greater size for experiments comparing Varint32 encoding
// of a vector of larger integrals vs a plain form.)
//
-template<typename T, typename A>
-CheckBool WriteVectorU8(const std::vector<T, A>& items, SinkStream* buffer) {
+template<typename V>
+CheckBool WriteVectorU8(const V& items, SinkStream* buffer) {
size_t count = items.size();
bool ok = buffer->WriteSizeVarint32(count);
if (count != 0 && ok) {
- size_t byte_count = count * sizeof(T);
+ size_t byte_count = count * sizeof(typename V::value_type);
ok = buffer->Write(static_cast<const void*>(&items[0]), byte_count);
}
return ok;
}
-template<typename T, typename A>
-bool ReadVectorU8(std::vector<T, A>* items, SourceStream* buffer) {
+template<typename V>
+bool ReadVectorU8(V* items, SourceStream* buffer) {
uint32 count;
if (!buffer->ReadVarint32(&count))
return false;
items->clear();
- // TODO(tommi): check error
- items->resize(count);
- if (count != 0) {
- size_t byte_count = count * sizeof(T);
+ bool ok = items->resize(count, 0);
+ if (ok && count != 0) {
+ size_t byte_count = count * sizeof(typename V::value_type);
return buffer->Read(static_cast<void*>(&((*items)[0])), byte_count);
}
- return true;
+ return ok;
}
////////////////////////////////////////////////////////////////////////////////
@@ -161,16 +157,17 @@ static const RVA kUnassignedRVA = static_cast<RVA>(-1);
CheckBool EncodedProgram::DefineLabelCommon(RvaVector* rvas,
int index,
RVA rva) {
- if (static_cast<int>(rvas->size()) <= index) {
- // TODO(tommi): handle error
- rvas->resize(index + 1, kUnassignedRVA);
- }
- if ((*rvas)[index] != kUnassignedRVA) {
- NOTREACHED() << "DefineLabel double assigned " << index;
+ bool ok = true;
+ if (static_cast<int>(rvas->size()) <= index)
+ ok = rvas->resize(index + 1, kUnassignedRVA);
+
+ if (ok) {
+ DCHECK_EQ((*rvas)[index], kUnassignedRVA)
+ << "DefineLabel double assigned " << index;
+ (*rvas)[index] = rva;
}
- (*rvas)[index] = rva;
- // TODO(tommi): Handle errors
- return true;
+
+ return ok;
}
void EncodedProgram::EndLabels() {
@@ -194,16 +191,14 @@ void EncodedProgram::FinishLabelsCommon(RvaVector* rvas) {
}
CheckBool EncodedProgram::AddOrigin(RVA origin) {
- //TODO(tommi): Handle errors
- ops_.push_back(ORIGIN);
- origins_.push_back(origin);
- return true;
+ return ops_.push_back(ORIGIN) && origins_.push_back(origin);
}
CheckBool EncodedProgram::AddCopy(uint32 count, const void* bytes) {
- //TODO(tommi): Handle errors
const uint8* source = static_cast<const uint8*>(bytes);
+ bool ok = true;
+
// Fold adjacent COPY instructions into one. This nearly halves the size of
// an EncodedProgram with only COPY1 instructions since there are approx plain
// 16 bytes per reloc. This has a working-set benefit during decompression.
@@ -213,49 +208,41 @@ CheckBool EncodedProgram::AddCopy(uint32 count, const void* bytes) {
if (!ops_.empty()) {
if (ops_.back() == COPY1) {
ops_.back() = COPY;
- copy_counts_.push_back(1);
+ ok = copy_counts_.push_back(1);
}
- if (ops_.back() == COPY) {
+ if (ok && ops_.back() == COPY) {
copy_counts_.back() += count;
- for (uint32 i = 0; i < count; ++i) {
- copy_bytes_.push_back(source[i]);
+ for (uint32 i = 0; ok && i < count; ++i) {
+ ok = copy_bytes_.push_back(source[i]);
}
- return true;
+ return ok;
}
}
- if (count == 1) {
- ops_.push_back(COPY1);
- copy_bytes_.push_back(source[0]);
- } else {
- ops_.push_back(COPY);
- copy_counts_.push_back(count);
- for (uint32 i = 0; i < count; ++i) {
- copy_bytes_.push_back(source[i]);
+ if (ok) {
+ if (count == 1) {
+ ok = ops_.push_back(COPY1) && copy_bytes_.push_back(source[0]);
+ } else {
+ ok = ops_.push_back(COPY) && copy_counts_.push_back(count);
+ for (uint32 i = 0; ok && i < count; ++i) {
+ ok = copy_bytes_.push_back(source[i]);
+ }
}
}
- return true;
+ return ok;
}
CheckBool EncodedProgram::AddAbs32(int label_index) {
- //TODO(tommi): Handle errors
- ops_.push_back(ABS32);
- abs32_ix_.push_back(label_index);
- return true;
+ return ops_.push_back(ABS32) && abs32_ix_.push_back(label_index);
}
CheckBool EncodedProgram::AddRel32(int label_index) {
- //TODO(tommi): Handle errors
- ops_.push_back(REL32);
- rel32_ix_.push_back(label_index);
- return true;
+ return ops_.push_back(REL32) && rel32_ix_.push_back(label_index);
}
CheckBool EncodedProgram::AddMakeRelocs() {
- //TODO(tommi): Handle errors
- ops_.push_back(MAKE_BASE_RELOCATION_TABLE);
- return true;
+ return ops_.push_back(MAKE_BASE_RELOCATION_TABLE);
}
void EncodedProgram::DebuggingSummary() {
@@ -393,8 +380,8 @@ bool EncodedProgram::ReadFrom(SourceStreamSet* streams) {
// Safe, non-throwing version of std::vector::at(). Returns 'true' for success,
// 'false' for out-of-bounds index error.
-template<typename T, typename A>
-bool VectorAt(const std::vector<T, A>& v, size_t index, T* output) {
+template<typename V, typename T>
+bool VectorAt(const V& v, size_t index, T* output) {
if (index >= v.size())
return false;
*output = v[index];
@@ -485,8 +472,7 @@ CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) {
if (!VectorAt(abs32_rva_, index, &rva))
return false;
uint32 abs32 = static_cast<uint32>(rva + image_base_);
- abs32_relocs_.push_back(current_rva);
- if (!output->Write(&abs32, 4))
+ if (!abs32_relocs_.push_back(current_rva) || !output->Write(&abs32, 4))
return false;
current_rva += 4;
break;
@@ -557,7 +543,7 @@ class RelocBlock {
pod.block_size += 2;
}
- CheckBool Flush(SinkStream* buffer) {
+ CheckBool Flush(SinkStream* buffer) WARN_UNUSED_RESULT {
bool ok = true;
if (pod.block_size != 8) {
if (pod.block_size % 4 != 0) { // Pad to make size multiple of 4 bytes.