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/adjustment_method.h" | 5 #include "courgette/adjustment_method.h" |
6 | 6 |
| 7 #include <stddef.h> |
| 8 #include <stdint.h> |
| 9 |
7 #include <algorithm> | 10 #include <algorithm> |
8 #include <list> | 11 #include <list> |
9 #include <map> | 12 #include <map> |
10 #include <set> | 13 #include <set> |
11 #include <string> | 14 #include <string> |
12 #include <vector> | 15 #include <vector> |
13 | 16 |
14 #include "base/basictypes.h" | |
15 #include "base/logging.h" | 17 #include "base/logging.h" |
| 18 #include "base/macros.h" |
16 #include "base/strings/string_number_conversions.h" | 19 #include "base/strings/string_number_conversions.h" |
17 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
18 #include "courgette/assembly_program.h" | 21 #include "courgette/assembly_program.h" |
19 #include "courgette/courgette.h" | 22 #include "courgette/courgette.h" |
20 #include "courgette/encoded_program.h" | 23 #include "courgette/encoded_program.h" |
21 | 24 |
22 namespace courgette { | 25 namespace courgette { |
23 | 26 |
24 //////////////////////////////////////////////////////////////////////////////// | 27 //////////////////////////////////////////////////////////////////////////////// |
25 | 28 |
26 class NullAdjustmentMethod : public AdjustmentMethod { | 29 class NullAdjustmentMethod : public AdjustmentMethod { |
27 bool Adjust(const AssemblyProgram& model, AssemblyProgram* program) { | 30 bool Adjust(const AssemblyProgram& model, AssemblyProgram* program) { |
28 return true; | 31 return true; |
29 } | 32 } |
30 }; | 33 }; |
31 | 34 |
32 //////////////////////////////////////////////////////////////////////////////// | 35 //////////////////////////////////////////////////////////////////////////////// |
33 | 36 |
34 // The purpose of adjustment is to assign indexes to Labels of a program 'p' to | 37 // The purpose of adjustment is to assign indexes to Labels of a program 'p' to |
35 // make the sequence of indexes similar to a 'model' program 'm'. Labels | 38 // make the sequence of indexes similar to a 'model' program 'm'. Labels |
36 // themselves don't have enough information to do this job, so we work with a | 39 // themselves don't have enough information to do this job, so we work with a |
37 // LabelInfo surrogate for each label. | 40 // LabelInfo surrogate for each label. |
38 // | 41 // |
39 class LabelInfo { | 42 class LabelInfo { |
40 public: | 43 public: |
41 Label* label_; // The label that this info a surrogate for. | 44 Label* label_; // The label that this info a surrogate for. |
42 | 45 |
43 // Information used only in debugging messages. | 46 // Information used only in debugging messages. |
44 uint32 is_model_ : 1; // Is the label in the model? | 47 uint32_t is_model_ : 1; // Is the label in the model? |
45 uint32 debug_index_ : 31; // An unique small number for naming the label. | 48 uint32_t debug_index_ : 31; // An unique small number for naming the label. |
46 | 49 |
47 uint32 refs_; // Number of times this Label is referenced. | 50 uint32_t refs_; // Number of times this Label is referenced. |
48 | 51 |
49 LabelInfo* assignment_; // Label from other program corresponding to this. | 52 LabelInfo* assignment_; // Label from other program corresponding to this. |
50 | 53 |
51 // LabelInfos are in a doubly linked list ordered by address (label_->rva_) so | 54 // LabelInfos are in a doubly linked list ordered by address (label_->rva_) so |
52 // we can quickly find Labels adjacent in address order. | 55 // we can quickly find Labels adjacent in address order. |
53 LabelInfo* next_addr_; // Label(Info) at next highest address. | 56 LabelInfo* next_addr_; // Label(Info) at next highest address. |
54 LabelInfo* prev_addr_; // Label(Info) at next lowest address. | 57 LabelInfo* prev_addr_; // Label(Info) at next lowest address. |
55 | 58 |
56 std::vector<uint32> positions_; // Offsets into the trace of references. | 59 std::vector<uint32_t> positions_; // Offsets into the trace of references. |
57 | 60 |
58 // Just a no-argument constructor and copy constructor. Actual LabelInfo | 61 // Just a no-argument constructor and copy constructor. Actual LabelInfo |
59 // objects are allocated in std::pair structs in a std::map. | 62 // objects are allocated in std::pair structs in a std::map. |
60 LabelInfo() | 63 LabelInfo() |
61 : label_(NULL), is_model_(false), debug_index_(0), refs_(0), | 64 : label_(NULL), is_model_(false), debug_index_(0), refs_(0), |
62 assignment_(NULL), | 65 assignment_(NULL), |
63 next_addr_(NULL), | 66 next_addr_(NULL), |
64 prev_addr_(NULL) {} | 67 prev_addr_(NULL) {} |
65 | 68 |
66 private: | 69 private: |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
142 int count_; // Frequency of this path in Trie. | 145 int count_; // Frequency of this path in Trie. |
143 int length_; | 146 int length_; |
144 typedef std::map<LabelInfo*, Node*> Edges; | 147 typedef std::map<LabelInfo*, Node*> Edges; |
145 Edges edges_; | 148 Edges edges_; |
146 std::vector<int> places_; // Indexes into sequence of this item. | 149 std::vector<int> places_; // Indexes into sequence of this item. |
147 std::list<Node*> edges_in_frequency_order; | 150 std::list<Node*> edges_in_frequency_order; |
148 | 151 |
149 bool in_queue_; | 152 bool in_queue_; |
150 bool Extended() const { return !edges_.empty(); } | 153 bool Extended() const { return !edges_.empty(); } |
151 | 154 |
152 uint32 Weight() const { | 155 uint32_t Weight() const { return edges_in_frequency_order.front()->count_; } |
153 return edges_in_frequency_order.front()->count_; | |
154 } | |
155 }; | 156 }; |
156 | 157 |
157 static std::string ToString(Node* node) { | 158 static std::string ToString(Node* node) { |
158 std::vector<std::string> prefix; | 159 std::vector<std::string> prefix; |
159 for (Node* n = node; n->prev_; n = n->prev_) | 160 for (Node* n = node; n->prev_; n = n->prev_) |
160 prefix.push_back(ToString(n->in_edge_)); | 161 prefix.push_back(ToString(n->in_edge_)); |
161 | 162 |
162 std::string s; | 163 std::string s; |
163 s += "{"; | 164 s += "{"; |
164 const char* sep = ""; | 165 const char* sep = ""; |
(...skipping 18 matching lines...) Expand all Loading... |
183 if (a->count_ != b->count_) | 184 if (a->count_ != b->count_) |
184 return (a->count_) > (b->count_); | 185 return (a->count_) > (b->count_); |
185 return a->places_.at(0) < b->places_.at(0); // Prefer first occuring. | 186 return a->places_.at(0) < b->places_.at(0); // Prefer first occuring. |
186 } | 187 } |
187 }; | 188 }; |
188 | 189 |
189 struct OrderNodeByWeightDecreasing { | 190 struct OrderNodeByWeightDecreasing { |
190 bool operator()(Node* a, Node* b) const { | 191 bool operator()(Node* a, Node* b) const { |
191 // (Maybe tie-break on total count, followed by lowest assigned node indexes | 192 // (Maybe tie-break on total count, followed by lowest assigned node indexes |
192 // in path.) | 193 // in path.) |
193 uint32 a_weight = a->Weight(); | 194 uint32_t a_weight = a->Weight(); |
194 uint32 b_weight = b->Weight(); | 195 uint32_t b_weight = b->Weight(); |
195 if (a_weight != b_weight) | 196 if (a_weight != b_weight) |
196 return a_weight > b_weight; | 197 return a_weight > b_weight; |
197 if (a->length_ != b->length_) | 198 if (a->length_ != b->length_) |
198 return a->length_ > b->length_; // Prefer longer. | 199 return a->length_ > b->length_; // Prefer longer. |
199 return a->places_.at(0) < b->places_.at(0); // Prefer first occuring. | 200 return a->places_.at(0) < b->places_.at(0); // Prefer first occuring. |
200 } | 201 } |
201 }; | 202 }; |
202 | 203 |
203 typedef std::set<Node*, OrderNodeByWeightDecreasing> NodeQueue; | 204 typedef std::set<Node*, OrderNodeByWeightDecreasing> NodeQueue; |
204 | 205 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 ExtendNode(node, p_trace_); | 248 ExtendNode(node, p_trace_); |
248 // SkipCommittedLabels(node); | 249 // SkipCommittedLabels(node); |
249 if (node->edges_in_frequency_order.empty()) | 250 if (node->edges_in_frequency_order.empty()) |
250 return; | 251 return; |
251 node->in_queue_ = true; | 252 node->in_queue_ = true; |
252 worklist_.insert(node); | 253 worklist_.insert(node); |
253 } | 254 } |
254 | 255 |
255 void SkipCommittedLabels(Node* node) { | 256 void SkipCommittedLabels(Node* node) { |
256 ExtendNode(node, p_trace_); | 257 ExtendNode(node, p_trace_); |
257 uint32 skipped = 0; | 258 uint32_t skipped = 0; |
258 while (!node->edges_in_frequency_order.empty() && | 259 while (!node->edges_in_frequency_order.empty() && |
259 node->edges_in_frequency_order.front()->in_edge_->assignment_) { | 260 node->edges_in_frequency_order.front()->in_edge_->assignment_) { |
260 ++skipped; | 261 ++skipped; |
261 node->edges_in_frequency_order.pop_front(); | 262 node->edges_in_frequency_order.pop_front(); |
262 } | 263 } |
263 if (skipped > 0) | 264 if (skipped > 0) |
264 VLOG(4) << "Skipped " << skipped << " at " << ToString(node); | 265 VLOG(4) << "Skipped " << skipped << " at " << ToString(node); |
265 } | 266 } |
266 | 267 |
267 void TrySolveNode(Node* p_node) { | 268 void TrySolveNode(Node* p_node) { |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
414 | 415 |
415 AssignOne(p_info_prev, m_info_prev); | 416 AssignOne(p_info_prev, m_info_prev); |
416 VLOG(4) << " Extending assignment <- " << ToString(p_info_prev) << " := " | 417 VLOG(4) << " Extending assignment <- " << ToString(p_info_prev) << " := " |
417 << ToString(m_info_prev); | 418 << ToString(m_info_prev); |
418 | 419 |
419 p_info_prev = p_info_prev_prev; | 420 p_info_prev = p_info_prev_prev; |
420 m_info_prev = m_info_prev_prev; | 421 m_info_prev = m_info_prev_prev; |
421 } | 422 } |
422 } | 423 } |
423 | 424 |
424 uint32 TryExtendSequence(uint32 p_pos_start, uint32 m_pos_start) { | 425 uint32_t TryExtendSequence(uint32_t p_pos_start, uint32_t m_pos_start) { |
425 uint32 p_pos = p_pos_start + 1; | 426 uint32_t p_pos = p_pos_start + 1; |
426 uint32 m_pos = m_pos_start + 1; | 427 uint32_t m_pos = m_pos_start + 1; |
427 | 428 |
428 while (p_pos < p_trace_.size() && m_pos < m_trace_.size()) { | 429 while (p_pos < p_trace_.size() && m_pos < m_trace_.size()) { |
429 LabelInfo* p_info = p_trace_[p_pos]; | 430 LabelInfo* p_info = p_trace_[p_pos]; |
430 LabelInfo* m_info = m_trace_[m_pos]; | 431 LabelInfo* m_info = m_trace_[m_pos]; |
431 | 432 |
432 // To match, either (1) both are assigned or (2) both are unassigned. | 433 // To match, either (1) both are assigned or (2) both are unassigned. |
433 if ((p_info->assignment_ == NULL) != (m_info->assignment_ == NULL)) | 434 if ((p_info->assignment_ == NULL) != (m_info->assignment_ == NULL)) |
434 break; | 435 break; |
435 | 436 |
436 // If they are assigned, it needs to be consistent (same index). | 437 // If they are assigned, it needs to be consistent (same index). |
(...skipping 12 matching lines...) Expand all Loading... |
449 VLOG(4) << " Extending assignment seq[+" << p_pos - p_pos_start | 450 VLOG(4) << " Extending assignment seq[+" << p_pos - p_pos_start |
450 << "] -> " << ToString(p_info) << " := " << ToString(m_info); | 451 << "] -> " << ToString(p_info) << " := " << ToString(m_info); |
451 | 452 |
452 ++p_pos; | 453 ++p_pos; |
453 ++m_pos; | 454 ++m_pos; |
454 } | 455 } |
455 | 456 |
456 return p_pos - p_pos_start; | 457 return p_pos - p_pos_start; |
457 } | 458 } |
458 | 459 |
459 uint32 TryExtendSequenceBackwards(uint32 p_pos_start, uint32 m_pos_start) { | 460 uint32_t TryExtendSequenceBackwards(uint32_t p_pos_start, |
| 461 uint32_t m_pos_start) { |
460 if (p_pos_start == 0 || m_pos_start == 0) | 462 if (p_pos_start == 0 || m_pos_start == 0) |
461 return 0; | 463 return 0; |
462 | 464 |
463 uint32 p_pos = p_pos_start - 1; | 465 uint32_t p_pos = p_pos_start - 1; |
464 uint32 m_pos = m_pos_start - 1; | 466 uint32_t m_pos = m_pos_start - 1; |
465 | 467 |
466 while (p_pos > 0 && m_pos > 0) { | 468 while (p_pos > 0 && m_pos > 0) { |
467 LabelInfo* p_info = p_trace_[p_pos]; | 469 LabelInfo* p_info = p_trace_[p_pos]; |
468 LabelInfo* m_info = m_trace_[m_pos]; | 470 LabelInfo* m_info = m_trace_[m_pos]; |
469 | 471 |
470 if ((p_info->assignment_ == NULL) != (m_info->assignment_ == NULL)) | 472 if ((p_info->assignment_ == NULL) != (m_info->assignment_ == NULL)) |
471 break; | 473 break; |
472 | 474 |
473 if (p_info->assignment_ && m_info->assignment_) { | 475 if (p_info->assignment_ && m_info->assignment_) { |
474 if (p_info->label_->index_ != m_info->label_->index_) | 476 if (p_info->label_->index_ != m_info->label_->index_) |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
515 VLOG(3) << "Expected defined edge in parent"; | 517 VLOG(3) << "Expected defined edge in parent"; |
516 return NULL; | 518 return NULL; |
517 } | 519 } |
518 | 520 |
519 return e->second; | 521 return e->second; |
520 } | 522 } |
521 | 523 |
522 Node* MakeRootNode(const Trace& trace) { | 524 Node* MakeRootNode(const Trace& trace) { |
523 Node* node = new Node(NULL, NULL); | 525 Node* node = new Node(NULL, NULL); |
524 all_nodes_.push_back(node); | 526 all_nodes_.push_back(node); |
525 for (uint32 i = 0; i < trace.size(); ++i) { | 527 for (uint32_t i = 0; i < trace.size(); ++i) { |
526 ++node->count_; | 528 ++node->count_; |
527 node->places_.push_back(i); | 529 node->places_.push_back(i); |
528 } | 530 } |
529 return node; | 531 return node; |
530 } | 532 } |
531 | 533 |
532 void ExtendNode(Node* node, const Trace& trace) { | 534 void ExtendNode(Node* node, const Trace& trace) { |
533 // Make sure trie is filled in at this node. | 535 // Make sure trie is filled in at this node. |
534 if (node->Extended()) | 536 if (node->Extended()) |
535 return; | 537 return; |
536 for (size_t i = 0; i < node->places_.size(); ++i) { | 538 for (size_t i = 0; i < node->places_.size(); ++i) { |
537 uint32 index = node->places_.at(i); | 539 uint32_t index = node->places_.at(i); |
538 if (index < trace.size()) { | 540 if (index < trace.size()) { |
539 LabelInfo* item = trace.at(index); | 541 LabelInfo* item = trace.at(index); |
540 Node*& slot = node->edges_[item]; | 542 Node*& slot = node->edges_[item]; |
541 if (slot == NULL) { | 543 if (slot == NULL) { |
542 slot = new Node(item, node); | 544 slot = new Node(item, node); |
543 all_nodes_.push_back(slot); | 545 all_nodes_.push_back(slot); |
544 node->edges_in_frequency_order.push_back(slot); | 546 node->edges_in_frequency_order.push_back(slot); |
545 } | 547 } |
546 slot->places_.push_back(index + 1); | 548 slot->places_.push_back(index + 1); |
547 ++slot->count_; | 549 ++slot->count_; |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 if (prev) prev->next_addr_ = curr; | 628 if (prev) prev->next_addr_ = curr; |
627 curr->prev_addr_ = prev; | 629 curr->prev_addr_ = prev; |
628 prev = curr; | 630 prev = curr; |
629 | 631 |
630 if (curr->positions_.size() != curr->refs_) | 632 if (curr->positions_.size() != curr->refs_) |
631 NOTREACHED(); | 633 NOTREACHED(); |
632 } | 634 } |
633 } | 635 } |
634 | 636 |
635 void ReferenceLabel(Trace* trace, Label* label, bool is_model) { | 637 void ReferenceLabel(Trace* trace, Label* label, bool is_model) { |
636 trace->push_back(MakeLabelInfo(label, is_model, | 638 trace->push_back( |
637 static_cast<uint32>(trace->size()))); | 639 MakeLabelInfo(label, is_model, static_cast<uint32_t>(trace->size()))); |
638 } | 640 } |
639 | 641 |
640 LabelInfo* MakeLabelInfo(Label* label, bool is_model, uint32 position) { | 642 LabelInfo* MakeLabelInfo(Label* label, bool is_model, uint32_t position) { |
641 LabelInfo& slot = label_infos_[label]; | 643 LabelInfo& slot = label_infos_[label]; |
642 if (slot.label_ == NULL) { | 644 if (slot.label_ == NULL) { |
643 slot.label_ = label; | 645 slot.label_ = label; |
644 slot.is_model_ = is_model; | 646 slot.is_model_ = is_model; |
645 slot.debug_index_ = ++debug_label_index_gen_; | 647 slot.debug_index_ = ++debug_label_index_gen_; |
646 } | 648 } |
647 slot.positions_.push_back(position); | 649 slot.positions_.push_back(position); |
648 ++slot.refs_; | 650 ++slot.refs_; |
649 return &slot; | 651 return &slot; |
650 } | 652 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
684 AdjustmentMethod* method = AdjustmentMethod::MakeProductionAdjustmentMethod(); | 686 AdjustmentMethod* method = AdjustmentMethod::MakeProductionAdjustmentMethod(); |
685 bool ok = method->Adjust(model, program); | 687 bool ok = method->Adjust(model, program); |
686 method->Destroy(); | 688 method->Destroy(); |
687 if (ok) | 689 if (ok) |
688 return C_OK; | 690 return C_OK; |
689 else | 691 else |
690 return C_ADJUSTMENT_FAILED; | 692 return C_ADJUSTMENT_FAILED; |
691 } | 693 } |
692 | 694 |
693 } // namespace courgette | 695 } // namespace courgette |
OLD | NEW |