| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 15 matching lines...) Expand all Loading... |
| 26 const int kStreamAbs32Indexes = 3; | 26 const int kStreamAbs32Indexes = 3; |
| 27 const int kStreamRel32Indexes = 4; | 27 const int kStreamRel32Indexes = 4; |
| 28 const int kStreamAbs32Addresses = 5; | 28 const int kStreamAbs32Addresses = 5; |
| 29 const int kStreamRel32Addresses = 6; | 29 const int kStreamRel32Addresses = 6; |
| 30 const int kStreamCopyCounts = 7; | 30 const int kStreamCopyCounts = 7; |
| 31 const int kStreamOriginAddresses = kStreamMisc; | 31 const int kStreamOriginAddresses = kStreamMisc; |
| 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 implicit 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, typename A> | 42 template<typename V> |
| 43 CheckBool WriteVector(const std::vector<T, A>& items, SinkStream* buffer) { | 43 CheckBool WriteVector(const V& items, SinkStream* buffer) { |
| 44 size_t count = items.size(); | 44 size_t count = items.size(); |
| 45 bool ok = buffer->WriteSizeVarint32(count); | 45 bool ok = buffer->WriteSizeVarint32(count); |
| 46 for (size_t i = 0; ok && i < count; ++i) { | 46 for (size_t i = 0; ok && i < count; ++i) { |
| 47 COMPILE_ASSERT(sizeof(T) <= sizeof(uint32), // NOLINT | 47 COMPILE_ASSERT(sizeof(items[0]) <= sizeof(uint32), // NOLINT |
| 48 T_must_fit_in_uint32); | 48 T_must_fit_in_uint32); |
| 49 ok = buffer->WriteSizeVarint32(items[i]); | 49 ok = buffer->WriteSizeVarint32(items[i]); |
| 50 } | 50 } |
| 51 return ok; | 51 return ok; |
| 52 } | 52 } |
| 53 | 53 |
| 54 template<typename T, typename A> | 54 template<typename V> |
| 55 bool ReadVector(std::vector<T, A>* items, SourceStream* buffer) { | 55 bool ReadVector(V* items, SourceStream* buffer) { |
| 56 uint32 count; | 56 uint32 count; |
| 57 if (!buffer->ReadVarint32(&count)) | 57 if (!buffer->ReadVarint32(&count)) |
| 58 return false; | 58 return false; |
| 59 | 59 |
| 60 items->clear(); | 60 items->clear(); |
| 61 items->reserve(count); | 61 |
| 62 for (size_t i = 0; i < count; ++i) { | 62 bool ok = items->reserve(count); |
| 63 for (size_t i = 0; ok && i < count; ++i) { |
| 63 uint32 item; | 64 uint32 item; |
| 64 if (!buffer->ReadVarint32(&item)) | 65 ok = buffer->ReadVarint32(&item); |
| 65 return false; | 66 if (ok) |
| 66 // TODO(tommi): Handle errors. | 67 ok = items->push_back(static_cast<V::value_type>(item)); |
| 67 items->push_back(static_cast<T>(item)); | |
| 68 } | 68 } |
| 69 | 69 |
| 70 return true; | 70 return ok; |
| 71 } | 71 } |
| 72 | 72 |
| 73 // Serializes a vector, using delta coding followed by Varint32 coding. | 73 // Serializes a vector, using delta coding followed by Varint32 coding. |
| 74 template<typename A> | 74 template<typename V> |
| 75 CheckBool WriteU32Delta(const std::vector<uint32, A>& set, SinkStream* buffer) { | 75 CheckBool WriteU32Delta(const V& set, SinkStream* buffer) { |
| 76 size_t count = set.size(); | 76 size_t count = set.size(); |
| 77 bool ok = buffer->WriteSizeVarint32(count); | 77 bool ok = buffer->WriteSizeVarint32(count); |
| 78 uint32 prev = 0; | 78 uint32 prev = 0; |
| 79 for (size_t i = 0; ok && i < count; ++i) { | 79 for (size_t i = 0; ok && i < count; ++i) { |
| 80 uint32 current = set[i]; | 80 uint32 current = set[i]; |
| 81 uint32 delta = current - prev; | 81 uint32 delta = current - prev; |
| 82 ok = buffer->WriteVarint32(delta); | 82 ok = buffer->WriteVarint32(delta); |
| 83 prev = current; | 83 prev = current; |
| 84 } | 84 } |
| 85 return ok; | 85 return ok; |
| 86 } | 86 } |
| 87 | 87 |
| 88 template <typename A> | 88 template <typename V> |
| 89 static CheckBool ReadU32Delta(std::vector<uint32, A>* set, | 89 static CheckBool ReadU32Delta(V* set, SourceStream* buffer) { |
| 90 SourceStream* buffer) { | |
| 91 uint32 count; | 90 uint32 count; |
| 92 | 91 |
| 93 if (!buffer->ReadVarint32(&count)) | 92 if (!buffer->ReadVarint32(&count)) |
| 94 return false; | 93 return false; |
| 95 | 94 |
| 96 set->clear(); | 95 set->clear(); |
| 97 // TODO(tommi): Handle errors. | 96 bool ok = set->reserve(count); |
| 98 set->reserve(count); | |
| 99 uint32 prev = 0; | 97 uint32 prev = 0; |
| 100 | 98 |
| 101 for (size_t i = 0; i < count; ++i) { | 99 for (size_t i = 0; ok && i < count; ++i) { |
| 102 uint32 delta; | 100 uint32 delta; |
| 103 if (!buffer->ReadVarint32(&delta)) | 101 ok = buffer->ReadVarint32(&delta); |
| 104 return false; | 102 if (ok) { |
| 105 uint32 current = prev + delta; | 103 uint32 current = prev + delta; |
| 106 // TODO(tommi): handle errors | 104 ok = set->push_back(current); |
| 107 set->push_back(current); | 105 prev = current; |
| 108 prev = current; | 106 } |
| 109 } | 107 } |
| 110 | 108 |
| 111 // TODO(tommi): Handle errors. | 109 return ok; |
| 112 return true; | |
| 113 } | 110 } |
| 114 | 111 |
| 115 // Write a vector as the byte representation of the contents. | 112 // Write a vector as the byte representation of the contents. |
| 116 // | 113 // |
| 117 // (This only really makes sense for a type T that has sizeof(T)==1, otherwise | 114 // (This only really makes sense for a type T that has sizeof(T)==1, otherwise |
| 118 // serialized representation is not endian-agnositic. But it is useful to keep | 115 // serialized representation is not endian-agnostic. But it is useful to keep |
| 119 // the possibility of a greater size for experiments comparing Varint32 encoding | 116 // the possibility of a greater size for experiments comparing Varint32 encoding |
| 120 // of a vector of larger integrals vs a plain form.) | 117 // of a vector of larger integrals vs a plain form.) |
| 121 // | 118 // |
| 122 template<typename T, typename A> | 119 template<typename V> |
| 123 CheckBool WriteVectorU8(const std::vector<T, A>& items, SinkStream* buffer) { | 120 CheckBool WriteVectorU8(const V& items, SinkStream* buffer) { |
| 124 size_t count = items.size(); | 121 size_t count = items.size(); |
| 125 bool ok = buffer->WriteSizeVarint32(count); | 122 bool ok = buffer->WriteSizeVarint32(count); |
| 126 if (count != 0 && ok) { | 123 if (count != 0 && ok) { |
| 127 size_t byte_count = count * sizeof(T); | 124 size_t byte_count = count * sizeof(V::value_type); |
| 128 ok = buffer->Write(static_cast<const void*>(&items[0]), byte_count); | 125 ok = buffer->Write(static_cast<const void*>(&items[0]), byte_count); |
| 129 } | 126 } |
| 130 return ok; | 127 return ok; |
| 131 } | 128 } |
| 132 | 129 |
| 133 template<typename T, typename A> | 130 template<typename V> |
| 134 bool ReadVectorU8(std::vector<T, A>* items, SourceStream* buffer) { | 131 bool ReadVectorU8(V* items, SourceStream* buffer) { |
| 135 uint32 count; | 132 uint32 count; |
| 136 if (!buffer->ReadVarint32(&count)) | 133 if (!buffer->ReadVarint32(&count)) |
| 137 return false; | 134 return false; |
| 138 | 135 |
| 139 items->clear(); | 136 items->clear(); |
| 140 // TODO(tommi): check error | 137 bool ok = items->resize(count, 0); |
| 141 items->resize(count); | 138 if (ok && count != 0) { |
| 142 if (count != 0) { | 139 size_t byte_count = count * sizeof(V::value_type); |
| 143 size_t byte_count = count * sizeof(T); | |
| 144 return buffer->Read(static_cast<void*>(&((*items)[0])), byte_count); | 140 return buffer->Read(static_cast<void*>(&((*items)[0])), byte_count); |
| 145 } | 141 } |
| 146 return true; | 142 return ok; |
| 147 } | 143 } |
| 148 | 144 |
| 149 //////////////////////////////////////////////////////////////////////////////// | 145 //////////////////////////////////////////////////////////////////////////////// |
| 150 | 146 |
| 151 CheckBool EncodedProgram::DefineRel32Label(int index, RVA value) { | 147 CheckBool EncodedProgram::DefineRel32Label(int index, RVA value) { |
| 152 return DefineLabelCommon(&rel32_rva_, index, value); | 148 return DefineLabelCommon(&rel32_rva_, index, value); |
| 153 } | 149 } |
| 154 | 150 |
| 155 CheckBool EncodedProgram::DefineAbs32Label(int index, RVA value) { | 151 CheckBool EncodedProgram::DefineAbs32Label(int index, RVA value) { |
| 156 return DefineLabelCommon(&abs32_rva_, index, value); | 152 return DefineLabelCommon(&abs32_rva_, index, value); |
| 157 } | 153 } |
| 158 | 154 |
| 159 static const RVA kUnassignedRVA = static_cast<RVA>(-1); | 155 static const RVA kUnassignedRVA = static_cast<RVA>(-1); |
| 160 | 156 |
| 161 CheckBool EncodedProgram::DefineLabelCommon(RvaVector* rvas, | 157 CheckBool EncodedProgram::DefineLabelCommon(RvaVector* rvas, |
| 162 int index, | 158 int index, |
| 163 RVA rva) { | 159 RVA rva) { |
| 164 if (static_cast<int>(rvas->size()) <= index) { | 160 bool ok = true; |
| 165 // TODO(tommi): handle error | 161 if (static_cast<int>(rvas->size()) <= index) |
| 166 rvas->resize(index + 1, kUnassignedRVA); | 162 ok = rvas->resize(index + 1, kUnassignedRVA); |
| 163 |
| 164 if (ok) { |
| 165 DCHECK_EQ((*rvas)[index], kUnassignedRVA) |
| 166 << "DefineLabel double assigned " << index; |
| 167 (*rvas)[index] = rva; |
| 167 } | 168 } |
| 168 if ((*rvas)[index] != kUnassignedRVA) { | 169 |
| 169 NOTREACHED() << "DefineLabel double assigned " << index; | 170 return ok; |
| 170 } | |
| 171 (*rvas)[index] = rva; | |
| 172 // TODO(tommi): Handle errors | |
| 173 return true; | |
| 174 } | 171 } |
| 175 | 172 |
| 176 void EncodedProgram::EndLabels() { | 173 void EncodedProgram::EndLabels() { |
| 177 FinishLabelsCommon(&abs32_rva_); | 174 FinishLabelsCommon(&abs32_rva_); |
| 178 FinishLabelsCommon(&rel32_rva_); | 175 FinishLabelsCommon(&rel32_rva_); |
| 179 } | 176 } |
| 180 | 177 |
| 181 void EncodedProgram::FinishLabelsCommon(RvaVector* rvas) { | 178 void EncodedProgram::FinishLabelsCommon(RvaVector* rvas) { |
| 182 // Replace all unassigned slots with the value at the previous index so they | 179 // Replace all unassigned slots with the value at the previous index so they |
| 183 // delta-encode to zero. (There might be better values than zero. The way to | 180 // delta-encode to zero. (There might be better values than zero. The way to |
| 184 // get that is have the higher level assembly program assign the unassigned | 181 // get that is have the higher level assembly program assign the unassigned |
| 185 // slots.) | 182 // slots.) |
| 186 RVA previous = 0; | 183 RVA previous = 0; |
| 187 size_t size = rvas->size(); | 184 size_t size = rvas->size(); |
| 188 for (size_t i = 0; i < size; ++i) { | 185 for (size_t i = 0; i < size; ++i) { |
| 189 if ((*rvas)[i] == kUnassignedRVA) | 186 if ((*rvas)[i] == kUnassignedRVA) |
| 190 (*rvas)[i] = previous; | 187 (*rvas)[i] = previous; |
| 191 else | 188 else |
| 192 previous = (*rvas)[i]; | 189 previous = (*rvas)[i]; |
| 193 } | 190 } |
| 194 } | 191 } |
| 195 | 192 |
| 196 CheckBool EncodedProgram::AddOrigin(RVA origin) { | 193 CheckBool EncodedProgram::AddOrigin(RVA origin) { |
| 197 //TODO(tommi): Handle errors | 194 return ops_.push_back(ORIGIN) && origins_.push_back(origin); |
| 198 ops_.push_back(ORIGIN); | |
| 199 origins_.push_back(origin); | |
| 200 return true; | |
| 201 } | 195 } |
| 202 | 196 |
| 203 CheckBool EncodedProgram::AddCopy(uint32 count, const void* bytes) { | 197 CheckBool EncodedProgram::AddCopy(uint32 count, const void* bytes) { |
| 204 //TODO(tommi): Handle errors | |
| 205 const uint8* source = static_cast<const uint8*>(bytes); | 198 const uint8* source = static_cast<const uint8*>(bytes); |
| 206 | 199 |
| 200 bool ok = true; |
| 201 |
| 207 // Fold adjacent COPY instructions into one. This nearly halves the size of | 202 // Fold adjacent COPY instructions into one. This nearly halves the size of |
| 208 // an EncodedProgram with only COPY1 instructions since there are approx plain | 203 // an EncodedProgram with only COPY1 instructions since there are approx plain |
| 209 // 16 bytes per reloc. This has a working-set benefit during decompression. | 204 // 16 bytes per reloc. This has a working-set benefit during decompression. |
| 210 // For compression of files with large differences this makes a small (4%) | 205 // For compression of files with large differences this makes a small (4%) |
| 211 // improvement in size. For files with small differences this degrades the | 206 // improvement in size. For files with small differences this degrades the |
| 212 // compressed size by 1.3% | 207 // compressed size by 1.3% |
| 213 if (!ops_.empty()) { | 208 if (!ops_.empty()) { |
| 214 if (ops_.back() == COPY1) { | 209 if (ops_.back() == COPY1) { |
| 215 ops_.back() = COPY; | 210 ops_.back() = COPY; |
| 216 copy_counts_.push_back(1); | 211 ok = copy_counts_.push_back(1); |
| 217 } | 212 } |
| 218 if (ops_.back() == COPY) { | 213 if (ok && ops_.back() == COPY) { |
| 219 copy_counts_.back() += count; | 214 copy_counts_.back() += count; |
| 220 for (uint32 i = 0; i < count; ++i) { | 215 for (uint32 i = 0; ok && i < count; ++i) { |
| 221 copy_bytes_.push_back(source[i]); | 216 ok = copy_bytes_.push_back(source[i]); |
| 222 } | 217 } |
| 223 return true; | 218 return ok; |
| 224 } | 219 } |
| 225 } | 220 } |
| 226 | 221 |
| 227 if (count == 1) { | 222 if (ok) { |
| 228 ops_.push_back(COPY1); | 223 if (count == 1) { |
| 229 copy_bytes_.push_back(source[0]); | 224 ok = ops_.push_back(COPY1) && copy_bytes_.push_back(source[0]); |
| 230 } else { | 225 } else { |
| 231 ops_.push_back(COPY); | 226 ok = ops_.push_back(COPY) && copy_counts_.push_back(count); |
| 232 copy_counts_.push_back(count); | 227 for (uint32 i = 0; ok && i < count; ++i) { |
| 233 for (uint32 i = 0; i < count; ++i) { | 228 ok = copy_bytes_.push_back(source[i]); |
| 234 copy_bytes_.push_back(source[i]); | 229 } |
| 235 } | 230 } |
| 236 } | 231 } |
| 237 | 232 |
| 238 return true; | 233 return ok; |
| 239 } | 234 } |
| 240 | 235 |
| 241 CheckBool EncodedProgram::AddAbs32(int label_index) { | 236 CheckBool EncodedProgram::AddAbs32(int label_index) { |
| 242 //TODO(tommi): Handle errors | 237 return ops_.push_back(ABS32) && abs32_ix_.push_back(label_index); |
| 243 ops_.push_back(ABS32); | |
| 244 abs32_ix_.push_back(label_index); | |
| 245 return true; | |
| 246 } | 238 } |
| 247 | 239 |
| 248 CheckBool EncodedProgram::AddRel32(int label_index) { | 240 CheckBool EncodedProgram::AddRel32(int label_index) { |
| 249 //TODO(tommi): Handle errors | 241 return ops_.push_back(REL32) && rel32_ix_.push_back(label_index); |
| 250 ops_.push_back(REL32); | |
| 251 rel32_ix_.push_back(label_index); | |
| 252 return true; | |
| 253 } | 242 } |
| 254 | 243 |
| 255 CheckBool EncodedProgram::AddMakeRelocs() { | 244 CheckBool EncodedProgram::AddMakeRelocs() { |
| 256 //TODO(tommi): Handle errors | 245 return ops_.push_back(MAKE_BASE_RELOCATION_TABLE); |
| 257 ops_.push_back(MAKE_BASE_RELOCATION_TABLE); | |
| 258 return true; | |
| 259 } | 246 } |
| 260 | 247 |
| 261 void EncodedProgram::DebuggingSummary() { | 248 void EncodedProgram::DebuggingSummary() { |
| 262 VLOG(1) << "EncodedProgram Summary" | 249 VLOG(1) << "EncodedProgram Summary" |
| 263 << "\n image base " << image_base_ | 250 << "\n image base " << image_base_ |
| 264 << "\n abs32 rvas " << abs32_rva_.size() | 251 << "\n abs32 rvas " << abs32_rva_.size() |
| 265 << "\n rel32 rvas " << rel32_rva_.size() | 252 << "\n rel32 rvas " << rel32_rva_.size() |
| 266 << "\n ops " << ops_.size() | 253 << "\n ops " << ops_.size() |
| 267 << "\n origins " << origins_.size() | 254 << "\n origins " << origins_.size() |
| 268 << "\n copy_counts " << copy_counts_.size() | 255 << "\n copy_counts " << copy_counts_.size() |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 386 for (int i = 0; i < kStreamLimit; ++i) { | 373 for (int i = 0; i < kStreamLimit; ++i) { |
| 387 if (streams->stream(i)->Remaining() > 0) | 374 if (streams->stream(i)->Remaining() > 0) |
| 388 return false; | 375 return false; |
| 389 } | 376 } |
| 390 | 377 |
| 391 return true; | 378 return true; |
| 392 } | 379 } |
| 393 | 380 |
| 394 // Safe, non-throwing version of std::vector::at(). Returns 'true' for success, | 381 // Safe, non-throwing version of std::vector::at(). Returns 'true' for success, |
| 395 // 'false' for out-of-bounds index error. | 382 // 'false' for out-of-bounds index error. |
| 396 template<typename T, typename A> | 383 template<typename V, typename T> |
| 397 bool VectorAt(const std::vector<T, A>& v, size_t index, T* output) { | 384 bool VectorAt(const V& v, size_t index, T* output) { |
| 398 if (index >= v.size()) | 385 if (index >= v.size()) |
| 399 return false; | 386 return false; |
| 400 *output = v[index]; | 387 *output = v[index]; |
| 401 return true; | 388 return true; |
| 402 } | 389 } |
| 403 | 390 |
| 404 CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) { | 391 CheckBool EncodedProgram::AssembleTo(SinkStream* final_buffer) { |
| 405 // For the most part, the assembly process walks the various tables. | 392 // For the most part, the assembly process walks the various tables. |
| 406 // ix_mumble is the index into the mumble table. | 393 // ix_mumble is the index into the mumble table. |
| 407 size_t ix_origins = 0; | 394 size_t ix_origins = 0; |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 478 | 465 |
| 479 case ABS32: { | 466 case ABS32: { |
| 480 uint32 index; | 467 uint32 index; |
| 481 if (!VectorAt(abs32_ix_, ix_abs32_ix, &index)) | 468 if (!VectorAt(abs32_ix_, ix_abs32_ix, &index)) |
| 482 return false; | 469 return false; |
| 483 ++ix_abs32_ix; | 470 ++ix_abs32_ix; |
| 484 RVA rva; | 471 RVA rva; |
| 485 if (!VectorAt(abs32_rva_, index, &rva)) | 472 if (!VectorAt(abs32_rva_, index, &rva)) |
| 486 return false; | 473 return false; |
| 487 uint32 abs32 = static_cast<uint32>(rva + image_base_); | 474 uint32 abs32 = static_cast<uint32>(rva + image_base_); |
| 488 abs32_relocs_.push_back(current_rva); | 475 if (!abs32_relocs_.push_back(current_rva) || !output->Write(&abs32, 4)) |
| 489 if (!output->Write(&abs32, 4)) | |
| 490 return false; | 476 return false; |
| 491 current_rva += 4; | 477 current_rva += 4; |
| 492 break; | 478 break; |
| 493 } | 479 } |
| 494 | 480 |
| 495 case MAKE_BASE_RELOCATION_TABLE: { | 481 case MAKE_BASE_RELOCATION_TABLE: { |
| 496 // We can see the base relocation anywhere, but we only have the | 482 // We can see the base relocation anywhere, but we only have the |
| 497 // information to generate it at the very end. So we divert the bytes | 483 // information to generate it at the very end. So we divert the bytes |
| 498 // we are generating to a temporary stream. | 484 // we are generating to a temporary stream. |
| 499 if (pending_base_relocation_table) // Can't have two base relocation | 485 if (pending_base_relocation_table) // Can't have two base relocation |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 614 if (assembled) | 600 if (assembled) |
| 615 return C_OK; | 601 return C_OK; |
| 616 return C_ASSEMBLY_FAILED; | 602 return C_ASSEMBLY_FAILED; |
| 617 } | 603 } |
| 618 | 604 |
| 619 void DeleteEncodedProgram(EncodedProgram* encoded) { | 605 void DeleteEncodedProgram(EncodedProgram* encoded) { |
| 620 delete encoded; | 606 delete encoded; |
| 621 } | 607 } |
| 622 | 608 |
| 623 } // end namespace | 609 } // end namespace |
| OLD | NEW |