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 |