Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(129)

Side by Side Diff: courgette/assembly_program.cc

Issue 1935203002: [Courgette] Using LabelManager to reduce Courgette-apply peak RAM by 25%. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « courgette/assembly_program.h ('k') | courgette/courgette.h » ('j') | courgette/courgette.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698