Chromium Code Reviews| 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/assembly_program.h" | 5 #include "courgette/assembly_program.h" |
| 6 | 6 |
| 7 #include <memory.h> | 7 #include <memory.h> |
| 8 #include <stddef.h> | 8 #include <stddef.h> |
| 9 #include <stdint.h> | 9 #include <stdint.h> |
| 10 | 10 |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 104 const uint8_t* arm_op_; | 104 const uint8_t* arm_op_; |
| 105 uint16_t op_size_; | 105 uint16_t op_size_; |
| 106 }; | 106 }; |
| 107 | 107 |
| 108 } // namespace | 108 } // namespace |
| 109 | 109 |
| 110 AssemblyProgram::AssemblyProgram(ExecutableType kind) | 110 AssemblyProgram::AssemblyProgram(ExecutableType kind) |
| 111 : kind_(kind), image_base_(0) { | 111 : kind_(kind), image_base_(0) { |
| 112 } | 112 } |
| 113 | 113 |
| 114 static void DeleteContainedLabels(const RVAToLabel& labels) { | |
| 115 for (RVAToLabel::const_iterator p = labels.begin(); p != labels.end(); ++p) | |
| 116 UncheckedDelete(p->second); | |
| 117 } | |
| 118 | |
| 119 AssemblyProgram::~AssemblyProgram() { | 114 AssemblyProgram::~AssemblyProgram() { |
| 120 for (size_t i = 0; i < instructions_.size(); ++i) { | 115 for (size_t i = 0; i < instructions_.size(); ++i) { |
| 121 Instruction* instruction = instructions_[i]; | 116 Instruction* instruction = instructions_[i]; |
| 122 if (instruction->op() != DEFBYTE) // Owned by byte_instruction_cache_. | 117 if (instruction->op() != DEFBYTE) // Owned by byte_instruction_cache_. |
| 123 UncheckedDelete(instruction); | 118 UncheckedDelete(instruction); |
| 124 } | 119 } |
| 125 if (byte_instruction_cache_.get()) { | 120 if (byte_instruction_cache_.get()) { |
| 126 for (size_t i = 0; i < 256; ++i) | 121 for (size_t i = 0; i < 256; ++i) |
| 127 UncheckedDelete(byte_instruction_cache_[i]); | 122 UncheckedDelete(byte_instruction_cache_[i]); |
| 128 } | 123 } |
| 129 DeleteContainedLabels(rel32_labels_); | |
| 130 DeleteContainedLabels(abs32_labels_); | |
| 131 } | 124 } |
| 132 | 125 |
| 133 CheckBool AssemblyProgram::EmitPeRelocsInstruction() { | 126 CheckBool AssemblyProgram::EmitPeRelocsInstruction() { |
| 134 return Emit(ScopedInstruction(UncheckedNew<PeRelocsInstruction>())); | 127 return Emit(ScopedInstruction(UncheckedNew<PeRelocsInstruction>())); |
| 135 } | 128 } |
| 136 | 129 |
| 137 CheckBool AssemblyProgram::EmitElfRelocationInstruction() { | 130 CheckBool AssemblyProgram::EmitElfRelocationInstruction() { |
| 138 return Emit(ScopedInstruction(UncheckedNew<ElfRelocsInstruction>())); | 131 return Emit(ScopedInstruction(UncheckedNew<ElfRelocsInstruction>())); |
| 139 } | 132 } |
| 140 | 133 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 171 CheckBool AssemblyProgram::EmitAbs32(Label* label) { | 164 CheckBool AssemblyProgram::EmitAbs32(Label* label) { |
| 172 return Emit( | 165 return Emit( |
| 173 ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS32, label))); | 166 ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS32, label))); |
| 174 } | 167 } |
| 175 | 168 |
| 176 CheckBool AssemblyProgram::EmitAbs64(Label* label) { | 169 CheckBool AssemblyProgram::EmitAbs64(Label* label) { |
| 177 return Emit( | 170 return Emit( |
| 178 ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS64, label))); | 171 ScopedInstruction(UncheckedNew<InstructionWithLabel>(ABS64, label))); |
| 179 } | 172 } |
| 180 | 173 |
| 181 Label* AssemblyProgram::FindOrMakeAbs32Label(RVA rva) { | 174 void AssemblyProgram::PrecomputeLabels(RvaVisitor* abs32_visitor, |
| 182 return FindLabel(rva, &abs32_labels_); | 175 RvaVisitor* rel32_visitor) { |
| 176 abs32_label_manager_.Read(abs32_visitor); | |
| 177 rel32_label_manager_.Read(rel32_visitor); | |
| 178 TrimLabels(); | |
| 183 } | 179 } |
| 184 | 180 |
| 185 Label* AssemblyProgram::FindOrMakeRel32Label(RVA rva) { | 181 // Chosen empirically to give the best reduction in payload size for |
| 186 return FindLabel(rva, &rel32_labels_); | 182 // an update from daisy_3701.98.0 to daisy_4206.0.0. |
| 183 const int AssemblyProgram::kLabelLowerLimit = 5; | |
|
Will Harris
2016/05/04 18:02:25
is this value of 5 still valid?
huangs
2016/05/04 19:33:59
Probably not -- but we'll need to experiment. Thi
| |
| 184 | |
| 185 void AssemblyProgram::TrimLabels() { | |
| 186 // For now only trim for ARM binaries. | |
| 187 if (kind() != EXE_ELF_32_ARM) | |
| 188 return; | |
| 189 | |
| 190 int lower_limit = kLabelLowerLimit; | |
| 191 | |
| 192 VLOG(1) << "TrimLabels: threshold " << lower_limit; | |
| 193 | |
| 194 rel32_label_manager_.RemoveUnderusedLabels(lower_limit); | |
| 195 } | |
| 196 | |
| 197 void AssemblyProgram::UnassignIndexes() { | |
| 198 abs32_label_manager_.UnassignIndexes(); | |
| 199 rel32_label_manager_.UnassignIndexes(); | |
| 187 } | 200 } |
| 188 | 201 |
| 189 void AssemblyProgram::DefaultAssignIndexes() { | 202 void AssemblyProgram::DefaultAssignIndexes() { |
| 190 DefaultAssignIndexes(&abs32_labels_); | 203 abs32_label_manager_.DefaultAssignIndexes(); |
| 191 DefaultAssignIndexes(&rel32_labels_); | 204 rel32_label_manager_.DefaultAssignIndexes(); |
| 192 } | |
| 193 | |
| 194 void AssemblyProgram::UnassignIndexes() { | |
| 195 UnassignIndexes(&abs32_labels_); | |
| 196 UnassignIndexes(&rel32_labels_); | |
| 197 } | 205 } |
| 198 | 206 |
| 199 void AssemblyProgram::AssignRemainingIndexes() { | 207 void AssemblyProgram::AssignRemainingIndexes() { |
| 200 AssignRemainingIndexes(&abs32_labels_); | 208 abs32_label_manager_.AssignRemainingIndexes(); |
| 201 AssignRemainingIndexes(&rel32_labels_); | 209 rel32_label_manager_.AssignRemainingIndexes(); |
| 210 } | |
| 211 | |
| 212 Label* AssemblyProgram::FindAbs32Label(RVA rva) { | |
| 213 return abs32_label_manager_.Find(rva); | |
| 214 } | |
| 215 | |
| 216 Label* AssemblyProgram::FindRel32Label(RVA rva) { | |
| 217 return rel32_label_manager_.Find(rva); | |
| 202 } | 218 } |
| 203 | 219 |
| 204 Label* AssemblyProgram::InstructionAbs32Label( | 220 Label* AssemblyProgram::InstructionAbs32Label( |
| 205 const Instruction* instruction) const { | 221 const Instruction* instruction) const { |
| 206 if (instruction->op() == ABS32) | 222 if (instruction->op() == ABS32) |
| 207 return static_cast<const InstructionWithLabel*>(instruction)->label(); | 223 return static_cast<const InstructionWithLabel*>(instruction)->label(); |
| 208 return NULL; | 224 return NULL; |
| 209 } | 225 } |
| 210 | 226 |
| 211 Label* AssemblyProgram::InstructionAbs64Label( | 227 Label* AssemblyProgram::InstructionAbs64Label( |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 231 // Ownership successfully passed to instructions_. | 247 // Ownership successfully passed to instructions_. |
| 232 ignore_result(instruction.release()); | 248 ignore_result(instruction.release()); |
| 233 return true; | 249 return true; |
| 234 } | 250 } |
| 235 | 251 |
| 236 CheckBool AssemblyProgram::EmitShared(Instruction* instruction) { | 252 CheckBool AssemblyProgram::EmitShared(Instruction* instruction) { |
| 237 DCHECK(!instruction || instruction->op() == DEFBYTE); | 253 DCHECK(!instruction || instruction->op() == DEFBYTE); |
| 238 return instruction && instructions_.push_back(instruction); | 254 return instruction && instructions_.push_back(instruction); |
| 239 } | 255 } |
| 240 | 256 |
| 241 Label* AssemblyProgram::FindLabel(RVA rva, RVAToLabel* labels) { | |
| 242 Label*& slot = (*labels)[rva]; | |
| 243 if (slot == NULL) { | |
| 244 slot = UncheckedNew<Label>(rva); | |
| 245 if (slot == NULL) | |
| 246 return NULL; | |
| 247 } | |
| 248 slot->count_++; | |
| 249 return slot; | |
| 250 } | |
| 251 | |
| 252 void AssemblyProgram::UnassignIndexes(RVAToLabel* labels) { | 257 void AssemblyProgram::UnassignIndexes(RVAToLabel* labels) { |
| 253 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) { | 258 for (RVAToLabel::iterator p = labels->begin(); p != labels->end(); ++p) { |
| 254 Label* current = p->second; | 259 Label* current = p->second; |
| 255 current->index_ = Label::kNoIndex; | 260 current->index_ = Label::kNoIndex; |
| 256 } | 261 } |
| 257 } | 262 } |
| 258 | 263 |
| 259 // DefaultAssignIndexes takes a set of labels and assigns indexes in increasing | 264 // DefaultAssignIndexes takes a set of labels and assigns indexes in increasing |
| 260 // address order. | 265 // address order. |
| 261 // | 266 // |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 360 VLOG(1) << " fill forward " << fill_forward_count | 365 VLOG(1) << " fill forward " << fill_forward_count |
| 361 << " backward " << fill_backward_count | 366 << " backward " << fill_backward_count |
| 362 << " infill " << fill_infill_count; | 367 << " infill " << fill_infill_count; |
| 363 } | 368 } |
| 364 | 369 |
| 365 std::unique_ptr<EncodedProgram> AssemblyProgram::Encode() const { | 370 std::unique_ptr<EncodedProgram> AssemblyProgram::Encode() const { |
| 366 std::unique_ptr<EncodedProgram> encoded(new EncodedProgram()); | 371 std::unique_ptr<EncodedProgram> encoded(new EncodedProgram()); |
| 367 | 372 |
| 368 encoded->set_image_base(image_base_); | 373 encoded->set_image_base(image_base_); |
| 369 | 374 |
| 370 if (!encoded->DefineLabels(abs32_labels_, rel32_labels_)) | 375 if (!encoded->ImportLabels(abs32_label_manager_, rel32_label_manager_)) |
| 371 return nullptr; | 376 return nullptr; |
| 372 | 377 |
| 373 for (size_t i = 0; i < instructions_.size(); ++i) { | 378 for (size_t i = 0; i < instructions_.size(); ++i) { |
| 374 Instruction* instruction = instructions_[i]; | 379 Instruction* instruction = instructions_[i]; |
| 375 | 380 |
| 376 switch (instruction->op()) { | 381 switch (instruction->op()) { |
| 377 case ORIGIN: { | 382 case ORIGIN: { |
| 378 OriginInstruction* org = static_cast<OriginInstruction*>(instruction); | 383 OriginInstruction* org = static_cast<OriginInstruction*>(instruction); |
| 379 if (!encoded->AddOrigin(org->origin_rva())) | 384 if (!encoded->AddOrigin(org->origin_rva())) |
| 380 return nullptr; | 385 return nullptr; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 463 UncheckedDelete(byte_instruction_cache_[j]); | 468 UncheckedDelete(byte_instruction_cache_[j]); |
| 464 byte_instruction_cache_.reset(); | 469 byte_instruction_cache_.reset(); |
| 465 return nullptr; | 470 return nullptr; |
| 466 } | 471 } |
| 467 } | 472 } |
| 468 } | 473 } |
| 469 | 474 |
| 470 return byte_instruction_cache_[byte]; | 475 return byte_instruction_cache_[byte]; |
| 471 } | 476 } |
| 472 | 477 |
| 473 // Chosen empirically to give the best reduction in payload size for | |
| 474 // an update from daisy_3701.98.0 to daisy_4206.0.0. | |
| 475 const int AssemblyProgram::kLabelLowerLimit = 5; | |
| 476 | |
| 477 CheckBool AssemblyProgram::TrimLabels() { | |
| 478 // For now only trim for ARM binaries. | |
| 479 if (kind() != EXE_ELF_32_ARM) | |
| 480 return true; | |
| 481 | |
| 482 int lower_limit = kLabelLowerLimit; | |
| 483 | |
| 484 VLOG(1) << "TrimLabels: threshold " << lower_limit; | |
| 485 | |
| 486 // Walk through the list of instructions, replacing trimmed labels | |
| 487 // with the original machine instruction. | |
| 488 for (size_t i = 0; i < instructions_.size(); ++i) { | |
| 489 Instruction* instruction = instructions_[i]; | |
| 490 switch (instruction->op()) { | |
| 491 case REL32ARM: { | |
| 492 Label* label = | |
| 493 static_cast<InstructionWithLabelARM*>(instruction)->label(); | |
| 494 if (label->count_ <= lower_limit) { | |
| 495 const uint8_t* arm_op = | |
| 496 static_cast<InstructionWithLabelARM*>(instruction)->arm_op(); | |
| 497 uint16_t op_size = | |
| 498 static_cast<InstructionWithLabelARM*>(instruction)->op_size(); | |
| 499 | |
| 500 if (op_size < 1) | |
| 501 return false; | |
| 502 UncheckedDelete(instruction); | |
| 503 instructions_[i] = UncheckedNew<BytesInstruction>(arm_op, op_size); | |
| 504 if (!instructions_[i]) | |
| 505 return false; | |
| 506 } | |
| 507 break; | |
| 508 } | |
| 509 default: | |
| 510 break; | |
| 511 } | |
| 512 } | |
| 513 | |
| 514 // Remove and deallocate underused Labels. | |
| 515 RVAToLabel::iterator it = rel32_labels_.begin(); | |
| 516 while (it != rel32_labels_.end()) { | |
| 517 if (it->second->count_ <= lower_limit) { | |
| 518 UncheckedDelete(it->second); | |
| 519 rel32_labels_.erase(it++); | |
| 520 } else { | |
| 521 ++it; | |
| 522 } | |
| 523 } | |
| 524 | |
| 525 return true; | |
| 526 } | |
| 527 | |
| 528 //////////////////////////////////////////////////////////////////////////////// | 478 //////////////////////////////////////////////////////////////////////////////// |
| 529 | 479 |
| 530 Status Encode(const AssemblyProgram& program, | 480 Status Encode(const AssemblyProgram& program, |
| 531 std::unique_ptr<EncodedProgram>* output) { | 481 std::unique_ptr<EncodedProgram>* output) { |
| 532 // Explicitly release any memory associated with the output before encoding. | 482 // Explicitly release any memory associated with the output before encoding. |
| 533 output->reset(); | 483 output->reset(); |
| 534 | 484 |
| 535 *output = program.Encode(); | 485 *output = program.Encode(); |
| 536 return (*output) ? C_OK : C_GENERAL_ERROR; | 486 return (*output) ? C_OK : C_GENERAL_ERROR; |
| 537 } | 487 } |
| 538 | 488 |
| 539 } // namespace courgette | 489 } // namespace courgette |
| OLD | NEW |