| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "courgette/encoded_program.h" | 5 #include "courgette/encoded_program.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | 10 #include <vector> |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 | 32 |
| 33 const int kStreamLimit = 9; | 33 const int kStreamLimit = 9; |
| 34 | 34 |
| 35 // Constructor is here rather than in the header. Although the constructor | 35 // Constructor is here rather than in the header. Although the constructor |
| 36 // appears to do nothing it is fact quite large because of the implict calls to | 36 // appears to do nothing it is fact quite large because of the implict calls to |
| 37 // field constructors. Ditto for the destructor. | 37 // field constructors. Ditto for the destructor. |
| 38 EncodedProgram::EncodedProgram() : image_base_(0) {} | 38 EncodedProgram::EncodedProgram() : image_base_(0) {} |
| 39 EncodedProgram::~EncodedProgram() {} | 39 EncodedProgram::~EncodedProgram() {} |
| 40 | 40 |
| 41 // Serializes a vector of integral values using Varint32 coding. | 41 // Serializes a vector of integral values using Varint32 coding. |
| 42 template<typename T> | 42 template<typename T, typename A> |
| 43 void WriteVector(const std::vector<T>& items, SinkStream* buffer) { | 43 void WriteVector(const std::vector<T, A>& items, SinkStream* buffer) { |
| 44 size_t count = items.size(); | 44 size_t count = items.size(); |
| 45 buffer->WriteSizeVarint32(count); | 45 buffer->WriteSizeVarint32(count); |
| 46 for (size_t i = 0; i < count; ++i) { | 46 for (size_t i = 0; i < count; ++i) { |
| 47 COMPILE_ASSERT(sizeof(T) <= sizeof(uint32), T_must_fit_in_uint32); | 47 COMPILE_ASSERT(sizeof(T) <= sizeof(uint32), // NOLINT |
| 48 T_must_fit_in_uint32); |
| 48 buffer->WriteSizeVarint32(items[i]); | 49 buffer->WriteSizeVarint32(items[i]); |
| 49 } | 50 } |
| 50 } | 51 } |
| 51 | 52 |
| 52 template<typename T> | 53 template<typename T, typename A> |
| 53 bool ReadVector(std::vector<T>* items, SourceStream* buffer) { | 54 bool ReadVector(std::vector<T, A>* items, SourceStream* buffer) { |
| 54 uint32 count; | 55 uint32 count; |
| 55 if (!buffer->ReadVarint32(&count)) | 56 if (!buffer->ReadVarint32(&count)) |
| 56 return false; | 57 return false; |
| 57 | 58 |
| 58 items->clear(); | 59 items->clear(); |
| 59 items->reserve(count); | 60 items->reserve(count); |
| 60 for (size_t i = 0; i < count; ++i) { | 61 for (size_t i = 0; i < count; ++i) { |
| 61 uint32 item; | 62 uint32 item; |
| 62 if (!buffer->ReadVarint32(&item)) | 63 if (!buffer->ReadVarint32(&item)) |
| 63 return false; | 64 return false; |
| 64 items->push_back(static_cast<T>(item)); | 65 items->push_back(static_cast<T>(item)); |
| 65 } | 66 } |
| 66 | 67 |
| 67 return true; | 68 return true; |
| 68 } | 69 } |
| 69 | 70 |
| 70 // Serializes a vector, using delta coding followed by Varint32 coding. | 71 // Serializes a vector, using delta coding followed by Varint32 coding. |
| 71 void WriteU32Delta(const std::vector<uint32>& set, SinkStream* buffer) { | 72 template<typename A> |
| 73 void WriteU32Delta(const std::vector<uint32, A>& set, SinkStream* buffer) { |
| 72 size_t count = set.size(); | 74 size_t count = set.size(); |
| 73 buffer->WriteSizeVarint32(count); | 75 buffer->WriteSizeVarint32(count); |
| 74 uint32 prev = 0; | 76 uint32 prev = 0; |
| 75 for (size_t i = 0; i < count; ++i) { | 77 for (size_t i = 0; i < count; ++i) { |
| 76 uint32 current = set[i]; | 78 uint32 current = set[i]; |
| 77 uint32 delta = current - prev; | 79 uint32 delta = current - prev; |
| 78 buffer->WriteVarint32(delta); | 80 buffer->WriteVarint32(delta); |
| 79 prev = current; | 81 prev = current; |
| 80 } | 82 } |
| 81 } | 83 } |
| 82 | 84 |
| 83 static bool ReadU32Delta(std::vector<uint32>* set, SourceStream* buffer) { | 85 template <typename A> |
| 86 static bool ReadU32Delta(std::vector<uint32, A>* set, SourceStream* buffer) { |
| 84 uint32 count; | 87 uint32 count; |
| 85 | 88 |
| 86 if (!buffer->ReadVarint32(&count)) | 89 if (!buffer->ReadVarint32(&count)) |
| 87 return false; | 90 return false; |
| 88 | 91 |
| 89 set->clear(); | 92 set->clear(); |
| 90 set->reserve(count); | 93 set->reserve(count); |
| 91 uint32 prev = 0; | 94 uint32 prev = 0; |
| 92 | 95 |
| 93 for (size_t i = 0; i < count; ++i) { | 96 for (size_t i = 0; i < count; ++i) { |
| 94 uint32 delta; | 97 uint32 delta; |
| 95 if (!buffer->ReadVarint32(&delta)) | 98 if (!buffer->ReadVarint32(&delta)) |
| 96 return false; | 99 return false; |
| 97 uint32 current = prev + delta; | 100 uint32 current = prev + delta; |
| 98 set->push_back(current); | 101 set->push_back(current); |
| 99 prev = current; | 102 prev = current; |
| 100 } | 103 } |
| 101 | 104 |
| 102 return true; | 105 return true; |
| 103 } | 106 } |
| 104 | 107 |
| 105 // Write a vector as the byte representation of the contents. | 108 // Write a vector as the byte representation of the contents. |
| 106 // | 109 // |
| 107 // (This only really makes sense for a type T that has sizeof(T)==1, otherwise | 110 // (This only really makes sense for a type T that has sizeof(T)==1, otherwise |
| 108 // serilized representation is not endian-agnositic. But it is useful to keep | 111 // serilized representation is not endian-agnositic. But it is useful to keep |
| 109 // the possibility of a greater size for experiments comparing Varint32 encoding | 112 // the possibility of a greater size for experiments comparing Varint32 encoding |
| 110 // of a vector of larger integrals vs a plain form.) | 113 // of a vector of larger integrals vs a plain form.) |
| 111 // | 114 // |
| 112 template<typename T> | 115 template<typename T, typename A> |
| 113 void WriteVectorU8(const std::vector<T>& items, SinkStream* buffer) { | 116 void WriteVectorU8(const std::vector<T, A>& items, SinkStream* buffer) { |
| 114 size_t count = items.size(); | 117 size_t count = items.size(); |
| 115 buffer->WriteSizeVarint32(count); | 118 buffer->WriteSizeVarint32(count); |
| 116 if (count != 0) { | 119 if (count != 0) { |
| 117 size_t byte_count = count * sizeof(T); | 120 size_t byte_count = count * sizeof(T); |
| 118 buffer->Write(static_cast<const void*>(&items[0]), byte_count); | 121 buffer->Write(static_cast<const void*>(&items[0]), byte_count); |
| 119 } | 122 } |
| 120 } | 123 } |
| 121 | 124 |
| 122 template<typename T> | 125 template<typename T, typename A> |
| 123 bool ReadVectorU8(std::vector<T>* items, SourceStream* buffer) { | 126 bool ReadVectorU8(std::vector<T, A>* items, SourceStream* buffer) { |
| 124 uint32 count; | 127 uint32 count; |
| 125 if (!buffer->ReadVarint32(&count)) | 128 if (!buffer->ReadVarint32(&count)) |
| 126 return false; | 129 return false; |
| 127 | 130 |
| 128 items->clear(); | 131 items->clear(); |
| 129 items->resize(count); | 132 items->resize(count); |
| 130 if (count != 0) { | 133 if (count != 0) { |
| 131 size_t byte_count = count * sizeof(T); | 134 size_t byte_count = count * sizeof(T); |
| 132 return buffer->Read(static_cast<void*>(&((*items)[0])), byte_count); | 135 return buffer->Read(static_cast<void*>(&((*items)[0])), byte_count); |
| 133 } | 136 } |
| 134 return true; | 137 return true; |
| 135 } | 138 } |
| 136 | 139 |
| 137 //////////////////////////////////////////////////////////////////////////////// | 140 //////////////////////////////////////////////////////////////////////////////// |
| 138 | 141 |
| 139 void EncodedProgram::DefineRel32Label(int index, RVA value) { | 142 void EncodedProgram::DefineRel32Label(int index, RVA value) { |
| 140 DefineLabelCommon(&rel32_rva_, index, value); | 143 DefineLabelCommon(&rel32_rva_, index, value); |
| 141 } | 144 } |
| 142 | 145 |
| 143 void EncodedProgram::DefineAbs32Label(int index, RVA value) { | 146 void EncodedProgram::DefineAbs32Label(int index, RVA value) { |
| 144 DefineLabelCommon(&abs32_rva_, index, value); | 147 DefineLabelCommon(&abs32_rva_, index, value); |
| 145 } | 148 } |
| 146 | 149 |
| 147 static const RVA kUnassignedRVA = static_cast<RVA>(-1); | 150 static const RVA kUnassignedRVA = static_cast<RVA>(-1); |
| 148 | 151 |
| 149 void EncodedProgram::DefineLabelCommon(std::vector<RVA>* rvas, | 152 void EncodedProgram::DefineLabelCommon(RvaVector* rvas, |
| 150 int index, | 153 int index, |
| 151 RVA rva) { | 154 RVA rva) { |
| 152 if (static_cast<int>(rvas->size()) <= index) { | 155 if (static_cast<int>(rvas->size()) <= index) { |
| 153 rvas->resize(index + 1, kUnassignedRVA); | 156 rvas->resize(index + 1, kUnassignedRVA); |
| 154 } | 157 } |
| 155 if ((*rvas)[index] != kUnassignedRVA) { | 158 if ((*rvas)[index] != kUnassignedRVA) { |
| 156 NOTREACHED() << "DefineLabel double assigned " << index; | 159 NOTREACHED() << "DefineLabel double assigned " << index; |
| 157 } | 160 } |
| 158 (*rvas)[index] = rva; | 161 (*rvas)[index] = rva; |
| 159 } | 162 } |
| 160 | 163 |
| 161 void EncodedProgram::EndLabels() { | 164 void EncodedProgram::EndLabels() { |
| 162 FinishLabelsCommon(&abs32_rva_); | 165 FinishLabelsCommon(&abs32_rva_); |
| 163 FinishLabelsCommon(&rel32_rva_); | 166 FinishLabelsCommon(&rel32_rva_); |
| 164 } | 167 } |
| 165 | 168 |
| 166 void EncodedProgram::FinishLabelsCommon(std::vector<RVA>* rvas) { | 169 void EncodedProgram::FinishLabelsCommon(RvaVector* rvas) { |
| 167 // Replace all unassigned slots with the value at the previous index so they | 170 // Replace all unassigned slots with the value at the previous index so they |
| 168 // delta-encode to zero. (There might be better values than zero. The way to | 171 // delta-encode to zero. (There might be better values than zero. The way to |
| 169 // get that is have the higher level assembly program assign the unassigned | 172 // get that is have the higher level assembly program assign the unassigned |
| 170 // slots.) | 173 // slots.) |
| 171 RVA previous = 0; | 174 RVA previous = 0; |
| 172 size_t size = rvas->size(); | 175 size_t size = rvas->size(); |
| 173 for (size_t i = 0; i < size; ++i) { | 176 for (size_t i = 0; i < size; ++i) { |
| 174 if ((*rvas)[i] == kUnassignedRVA) | 177 if ((*rvas)[i] == kUnassignedRVA) |
| 175 (*rvas)[i] = previous; | 178 (*rvas)[i] = previous; |
| 176 else | 179 else |
| 177 previous = (*rvas)[i]; | 180 previous = (*rvas)[i]; |
| 178 } | 181 } |
| 179 } | 182 } |
| 180 | 183 |
| 181 void EncodedProgram::AddOrigin(RVA origin) { | 184 void EncodedProgram::AddOrigin(RVA origin) { |
| 182 ops_.push_back(ORIGIN); | 185 ops_.push_back(ORIGIN); |
| 183 origins_.push_back(origin); | 186 origins_.push_back(origin); |
| 184 } | 187 } |
| 185 | 188 |
| 186 void EncodedProgram::AddCopy(int count, const void* bytes) { | 189 void EncodedProgram::AddCopy(uint32 count, const void* bytes) { |
| 187 const uint8* source = static_cast<const uint8*>(bytes); | 190 const uint8* source = static_cast<const uint8*>(bytes); |
| 188 | 191 |
| 189 // Fold adjacent COPY instructions into one. This nearly halves the size of | 192 // Fold adjacent COPY instructions into one. This nearly halves the size of |
| 190 // an EncodedProgram with only COPY1 instructions since there are approx plain | 193 // an EncodedProgram with only COPY1 instructions since there are approx plain |
| 191 // 16 bytes per reloc. This has a working-set benefit during decompression. | 194 // 16 bytes per reloc. This has a working-set benefit during decompression. |
| 192 // For compression of files with large differences this makes a small (4%) | 195 // For compression of files with large differences this makes a small (4%) |
| 193 // improvement in size. For files with small differences this degrades the | 196 // improvement in size. For files with small differences this degrades the |
| 194 // compressed size by 1.3% | 197 // compressed size by 1.3% |
| 195 if (ops_.size() > 0) { | 198 if (ops_.size() > 0) { |
| 196 if (ops_.back() == COPY1) { | 199 if (ops_.back() == COPY1) { |
| 197 ops_.back() = COPY; | 200 ops_.back() = COPY; |
| 198 copy_counts_.push_back(1); | 201 copy_counts_.push_back(1); |
| 199 } | 202 } |
| 200 if (ops_.back() == COPY) { | 203 if (ops_.back() == COPY) { |
| 201 copy_counts_.back() += count; | 204 copy_counts_.back() += count; |
| 202 for (int i = 0; i < count; ++i) { | 205 for (uint32 i = 0; i < count; ++i) { |
| 203 copy_bytes_.push_back(source[i]); | 206 copy_bytes_.push_back(source[i]); |
| 204 } | 207 } |
| 205 return; | 208 return; |
| 206 } | 209 } |
| 207 } | 210 } |
| 208 | 211 |
| 209 if (count == 1) { | 212 if (count == 1) { |
| 210 ops_.push_back(COPY1); | 213 ops_.push_back(COPY1); |
| 211 copy_bytes_.push_back(source[0]); | 214 copy_bytes_.push_back(source[0]); |
| 212 } else { | 215 } else { |
| 213 ops_.push_back(COPY); | 216 ops_.push_back(COPY); |
| 214 copy_counts_.push_back(count); | 217 copy_counts_.push_back(count); |
| 215 for (int i = 0; i < count; ++i) { | 218 for (uint32 i = 0; i < count; ++i) { |
| 216 copy_bytes_.push_back(source[i]); | 219 copy_bytes_.push_back(source[i]); |
| 217 } | 220 } |
| 218 } | 221 } |
| 219 } | 222 } |
| 220 | 223 |
| 221 void EncodedProgram::AddAbs32(int label_index) { | 224 void EncodedProgram::AddAbs32(int label_index) { |
| 222 ops_.push_back(ABS32); | 225 ops_.push_back(ABS32); |
| 223 abs32_ix_.push_back(label_index); | 226 abs32_ix_.push_back(label_index); |
| 224 } | 227 } |
| 225 | 228 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 342 for (int i = 0; i < kStreamLimit; ++i) { | 345 for (int i = 0; i < kStreamLimit; ++i) { |
| 343 if (streams->stream(i)->Remaining() > 0) | 346 if (streams->stream(i)->Remaining() > 0) |
| 344 return false; | 347 return false; |
| 345 } | 348 } |
| 346 | 349 |
| 347 return true; | 350 return true; |
| 348 } | 351 } |
| 349 | 352 |
| 350 // Safe, non-throwing version of std::vector::at(). Returns 'true' for success, | 353 // Safe, non-throwing version of std::vector::at(). Returns 'true' for success, |
| 351 // 'false' for out-of-bounds index error. | 354 // 'false' for out-of-bounds index error. |
| 352 template<typename T> | 355 template<typename T, typename A> |
| 353 bool VectorAt(const std::vector<T>& v, size_t index, T* output) { | 356 bool VectorAt(const std::vector<T, A>& v, size_t index, T* output) { |
| 354 if (index >= v.size()) | 357 if (index >= v.size()) |
| 355 return false; | 358 return false; |
| 356 *output = v[index]; | 359 *output = v[index]; |
| 357 return true; | 360 return true; |
| 358 } | 361 } |
| 359 | 362 |
| 360 bool EncodedProgram::AssembleTo(SinkStream* final_buffer) { | 363 bool EncodedProgram::AssembleTo(SinkStream* final_buffer) { |
| 361 // For the most part, the assembly process walks the various tables. | 364 // For the most part, the assembly process walks the various tables. |
| 362 // ix_mumble is the index into the mumble table. | 365 // ix_mumble is the index into the mumble table. |
| 363 size_t ix_origins = 0; | 366 size_t ix_origins = 0; |
| (...skipping 19 matching lines...) Expand all Loading... |
| 383 case ORIGIN: { | 386 case ORIGIN: { |
| 384 RVA section_rva; | 387 RVA section_rva; |
| 385 if (!VectorAt(origins_, ix_origins, §ion_rva)) | 388 if (!VectorAt(origins_, ix_origins, §ion_rva)) |
| 386 return false; | 389 return false; |
| 387 ++ix_origins; | 390 ++ix_origins; |
| 388 current_rva = section_rva; | 391 current_rva = section_rva; |
| 389 break; | 392 break; |
| 390 } | 393 } |
| 391 | 394 |
| 392 case COPY: { | 395 case COPY: { |
| 393 int count; | 396 uint32 count; |
| 394 if (!VectorAt(copy_counts_, ix_copy_counts, &count)) | 397 if (!VectorAt(copy_counts_, ix_copy_counts, &count)) |
| 395 return false; | 398 return false; |
| 396 ++ix_copy_counts; | 399 ++ix_copy_counts; |
| 397 for (int i = 0; i < count; ++i) { | 400 for (uint32 i = 0; i < count; ++i) { |
| 398 uint8 b; | 401 uint8 b; |
| 399 if (!VectorAt(copy_bytes_, ix_copy_bytes, &b)) | 402 if (!VectorAt(copy_bytes_, ix_copy_bytes, &b)) |
| 400 return false; | 403 return false; |
| 401 ++ix_copy_bytes; | 404 ++ix_copy_bytes; |
| 402 output->Write(&b, 1); | 405 output->Write(&b, 1); |
| 403 } | 406 } |
| 404 current_rva += count; | 407 current_rva += count; |
| 405 break; | 408 break; |
| 406 } | 409 } |
| 407 | 410 |
| (...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 if (assembled) | 563 if (assembled) |
| 561 return C_OK; | 564 return C_OK; |
| 562 return C_ASSEMBLY_FAILED; | 565 return C_ASSEMBLY_FAILED; |
| 563 } | 566 } |
| 564 | 567 |
| 565 void DeleteEncodedProgram(EncodedProgram* encoded) { | 568 void DeleteEncodedProgram(EncodedProgram* encoded) { |
| 566 delete encoded; | 569 delete encoded; |
| 567 } | 570 } |
| 568 | 571 |
| 569 } // end namespace | 572 } // end namespace |
| OLD | NEW |