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

Side by Side Diff: src/hydrogen-check-elimination.cc

Issue 130053007: [Sheriff] Revert "Check elimination temporarily disabled.", "Fix for buildbot failure after r19102.… (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 10 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 | Annotate | Revision Log
« no previous file with comments | « src/flag-definitions.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 30 matching lines...) Expand all
41 // For code de-uglification. 41 // For code de-uglification.
42 #define TRACE(x) if (FLAG_trace_check_elimination) PrintF x 42 #define TRACE(x) if (FLAG_trace_check_elimination) PrintF x
43 43
44 namespace v8 { 44 namespace v8 {
45 namespace internal { 45 namespace internal {
46 46
47 typedef UniqueSet<Map>* MapSet; 47 typedef UniqueSet<Map>* MapSet;
48 48
49 struct HCheckTableEntry { 49 struct HCheckTableEntry {
50 HValue* object_; // The object being approximated. NULL => invalid entry. 50 HValue* object_; // The object being approximated. NULL => invalid entry.
51 HInstruction* check_; // The last check instruction. 51 HValue* check_; // The last check instruction.
52 MapSet maps_; // The set of known maps for the object. 52 MapSet maps_; // The set of known maps for the object.
53 }; 53 };
54 54
55 55
56 // The main data structure used during check elimination, which stores a 56 // The main datastructure used during check elimination, which stores a
57 // set of known maps for each object. 57 // set of known maps for each object.
58 class HCheckTable : public ZoneObject { 58 class HCheckTable : public ZoneObject {
59 public: 59 public:
60 static const int kMaxTrackedObjects = 10; 60 static const int kMaxTrackedObjects = 10;
61 61
62 explicit HCheckTable(HCheckEliminationPhase* phase) 62 explicit HCheckTable(HCheckEliminationPhase* phase)
63 : phase_(phase), 63 : phase_(phase),
64 cursor_(0), 64 cursor_(0),
65 size_(0) { 65 size_(0) {
66 } 66 }
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
123 HCheckTableEntry* old_entry = &entries_[i]; 123 HCheckTableEntry* old_entry = &entries_[i];
124 HCheckTableEntry* new_entry = &copy->entries_[i]; 124 HCheckTableEntry* new_entry = &copy->entries_[i];
125 // TODO(titzer): keep the check if this block dominates the successor? 125 // TODO(titzer): keep the check if this block dominates the successor?
126 new_entry->object_ = old_entry->object_; 126 new_entry->object_ = old_entry->object_;
127 new_entry->check_ = NULL; 127 new_entry->check_ = NULL;
128 new_entry->maps_ = old_entry->maps_->Copy(phase_->zone()); 128 new_entry->maps_ = old_entry->maps_->Copy(phase_->zone());
129 } 129 }
130 copy->cursor_ = cursor_; 130 copy->cursor_ = cursor_;
131 copy->size_ = size_; 131 copy->size_ = size_;
132 132
133 // Create entries for succ block's phis.
134 if (succ->phis()->length() > 0) {
135 int pred_index = succ->PredecessorIndexOf(from_block);
136 for (int phi_index = 0;
137 phi_index < succ->phis()->length();
138 ++phi_index) {
139 HPhi* phi = succ->phis()->at(phi_index);
140 HValue* phi_operand = phi->OperandAt(pred_index);
141
142 HCheckTableEntry* pred_entry = copy->Find(phi_operand);
143 if (pred_entry != NULL) {
144 // Create an entry for a phi in the table.
145 copy->Insert(phi, NULL, pred_entry->maps_->Copy(phase_->zone()));
146 }
147 }
148 }
149
150 // Branch-sensitive analysis for certain comparisons may add more facts 133 // Branch-sensitive analysis for certain comparisons may add more facts
151 // to the state for the successor on the true branch. 134 // to the state for the successor on the true branch.
152 bool learned = false; 135 bool learned = false;
153 HControlInstruction* end = succ->predecessors()->at(0)->end(); 136 HControlInstruction* end = succ->predecessors()->at(0)->end();
154 if (succ->predecessors()->length() == 1 && end->SuccessorAt(0) == succ) { 137 if (succ->predecessors()->length() == 1 && end->SuccessorAt(0) == succ) {
155 if (end->IsCompareMap()) { 138 if (end->IsCompareMap()) {
156 // Learn on the true branch of if(CompareMap(x)). 139 // Learn on the true branch of if(CompareMap(x)).
157 HCompareMap* cmp = HCompareMap::cast(end); 140 HCompareMap* cmp = HCompareMap::cast(end);
158 HValue* object = cmp->value()->ActualValue(); 141 HValue* object = cmp->value()->ActualValue();
159 HCheckTableEntry* entry = copy->Find(object); 142 HCheckTableEntry* entry = copy->Find(object);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 learned ? "learned" : "copied", 178 learned ? "learned" : "copied",
196 from_block->block_id()); 179 from_block->block_id());
197 copy->Print(); 180 copy->Print();
198 } 181 }
199 182
200 return copy; 183 return copy;
201 } 184 }
202 185
203 // Global analysis: Merge this state with the other incoming state. 186 // Global analysis: Merge this state with the other incoming state.
204 HCheckTable* Merge(HBasicBlock* succ, HCheckTable* that, 187 HCheckTable* Merge(HBasicBlock* succ, HCheckTable* that,
205 HBasicBlock* pred_block, Zone* zone) { 188 HBasicBlock* that_block, Zone* zone) {
206 if (pred_block->IsReachable()) { 189 if (that_block->IsReachable()) {
207 if (that->size_ == 0) { 190 if (that->size_ == 0) {
208 // If the other state is empty, simply reset. 191 // If the other state is empty, simply reset.
209 size_ = 0; 192 size_ = 0;
210 cursor_ = 0; 193 cursor_ = 0;
211 } else { 194 } else {
212 int pred_index = succ->PredecessorIndexOf(pred_block);
213 bool compact = false; 195 bool compact = false;
214 for (int i = 0; i < size_; i++) { 196 for (int i = 0; i < size_; i++) {
215 HCheckTableEntry* this_entry = &entries_[i]; 197 HCheckTableEntry* this_entry = &entries_[i];
216 HCheckTableEntry* that_entry; 198 HCheckTableEntry* that_entry = that->Find(this_entry->object_);
217 if (this_entry->object_->IsPhi() &&
218 this_entry->object_->block() == succ) {
219 HPhi* phi = HPhi::cast(this_entry->object_);
220 HValue* phi_operand = phi->OperandAt(pred_index);
221 that_entry = that->Find(phi_operand);
222
223 } else {
224 that_entry = that->Find(this_entry->object_);
225 }
226
227 if (that_entry == NULL) { 199 if (that_entry == NULL) {
228 this_entry->object_ = NULL; 200 this_entry->object_ = NULL;
229 compact = true; 201 compact = true;
230 } else { 202 } else {
231 this_entry->maps_ = 203 this_entry->maps_ =
232 this_entry->maps_->Union(that_entry->maps_, phase_->zone()); 204 this_entry->maps_->Union(that_entry->maps_, phase_->zone());
233 if (this_entry->check_ != that_entry->check_) { 205 if (this_entry->check_ != that_entry->check_) {
234 this_entry->check_ = NULL; 206 this_entry->check_ = NULL;
235 } 207 }
236 ASSERT(this_entry->maps_->size() > 0); 208 ASSERT(this_entry->maps_->size() > 0);
237 } 209 }
238 } 210 }
239 if (compact) Compact(); 211 if (compact) Compact();
240 } 212 }
241 } 213 }
242 if (FLAG_trace_check_elimination) { 214 if (FLAG_trace_check_elimination) {
243 PrintF("B%d checkmaps-table merged with B%d table:\n", 215 PrintF("B%d checkmaps-table merged with B%d table:\n",
244 succ->block_id(), pred_block->block_id()); 216 succ->block_id(), that_block->block_id());
245 Print(); 217 Print();
246 } 218 }
247 return this; 219 return this;
248 } 220 }
249 221
250 void ReduceCheckMaps(HCheckMaps* instr) { 222 void ReduceCheckMaps(HCheckMaps* instr) {
251 HValue* object = instr->value()->ActualValue(); 223 HValue* object = instr->value()->ActualValue();
252 HCheckTableEntry* entry = Find(object); 224 HCheckTableEntry* entry = Find(object);
253 if (entry != NULL) { 225 if (entry != NULL) {
254 // entry found; 226 // entry found;
(...skipping 10 matching lines...) Expand all
265 TRACE(("Marking redundant CheckMaps #%d at B%d as dead\n", 237 TRACE(("Marking redundant CheckMaps #%d at B%d as dead\n",
266 instr->id(), instr->block()->block_id())); 238 instr->id(), instr->block()->block_id()));
267 // Mark check as dead but leave it in the graph as a checkpoint for 239 // Mark check as dead but leave it in the graph as a checkpoint for
268 // subsequent checks. 240 // subsequent checks.
269 instr->SetFlag(HValue::kIsDead); 241 instr->SetFlag(HValue::kIsDead);
270 entry->check_ = instr; 242 entry->check_ = instr;
271 INC_STAT(removed_); 243 INC_STAT(removed_);
272 } 244 }
273 return; 245 return;
274 } 246 }
275 MapSet intersection = i->Intersect(a, phase_->zone()); 247 i = i->Intersect(a, phase_->zone());
276 if (intersection->size() == 0) { 248 if (i->size() == 0) {
277 // Intersection is empty; probably megamorphic, which is likely to 249 // Intersection is empty; probably megamorphic, which is likely to
278 // deopt anyway, so just leave things as they are. 250 // deopt anyway, so just leave things as they are.
279 INC_STAT(empty_); 251 INC_STAT(empty_);
280 } else { 252 } else {
281 // Update set of maps in the entry. 253 // TODO(titzer): replace the first check with a more strict check
282 entry->maps_ = intersection; 254 INC_STAT(narrowed_);
283 if (intersection->size() != i->size()) {
284 // Narrow set of maps in the second check maps instruction.
285 HGraph* graph = instr->block()->graph();
286 HCheckMaps* new_check_maps =
287 HCheckMaps::New(graph->zone(), NULL, instr->value(),
288 intersection, instr->typecheck(),
289 instr->has_migration_target());
290 if (entry->check_ != NULL &&
291 entry->check_->block() == instr->block()) {
292 // There is a check in the same block so replace it with a more
293 // strict check and eliminate the second check entirely.
294 new_check_maps->InsertBefore(entry->check_);
295 entry->check_->DeleteAndReplaceWith(new_check_maps);
296 TRACE(("Check #%d narrowed to #%d\n",
297 entry->check_->id(), new_check_maps->id()));
298
299 } else {
300 new_check_maps->InsertBefore(instr);
301 }
302 TRACE(("CheckMaps #%d for #%d narrowed to #%d:\n",
303 instr->id(), instr->value()->id(), new_check_maps->id()));
304 instr->DeleteAndReplaceWith(new_check_maps);
305 entry->check_ = new_check_maps;
306
307 if (FLAG_trace_check_elimination) {
308 Print();
309 }
310 INC_STAT(narrowed_);
311 }
312 } 255 }
313 } else { 256 } else {
314 // No entry; insert a new one. 257 // No entry; insert a new one.
315 Insert(object, instr, instr->map_set().Copy(phase_->zone())); 258 Insert(object, instr, instr->map_set().Copy(phase_->zone()));
316 } 259 }
317 } 260 }
318 261
319 void ReduceCheckValue(HCheckValue* instr) { 262 void ReduceCheckValue(HCheckValue* instr) {
320 // Canonicalize HCheckValues; they might have their values load-eliminated. 263 // Canonicalize HCheckValues; they might have their values load-eliminated.
321 HValue* value = instr->Canonicalize(); 264 HValue* value = instr->Canonicalize();
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
476 OS::MemMove(&entries_[R], &tmp_entries[0], L * sizeof(HCheckTableEntry)); 419 OS::MemMove(&entries_[R], &tmp_entries[0], L * sizeof(HCheckTableEntry));
477 } 420 }
478 421
479 cursor_ = size_; // Move cursor to end. 422 cursor_ = size_; // Move cursor to end.
480 } 423 }
481 424
482 void Print() { 425 void Print() {
483 for (int i = 0; i < size_; i++) { 426 for (int i = 0; i < size_; i++) {
484 HCheckTableEntry* entry = &entries_[i]; 427 HCheckTableEntry* entry = &entries_[i];
485 ASSERT(entry->object_ != NULL); 428 ASSERT(entry->object_ != NULL);
486 PrintF(" checkmaps-table @%d: %s #%d ", i, 429 PrintF(" checkmaps-table @%d: object #%d ", i, entry->object_->id());
487 entry->object_->IsPhi() ? "phi" : "object",
488 entry->object_->id());
489 if (entry->check_ != NULL) { 430 if (entry->check_ != NULL) {
490 PrintF("check #%d ", entry->check_->id()); 431 PrintF("check #%d ", entry->check_->id());
491 } 432 }
492 MapSet list = entry->maps_; 433 MapSet list = entry->maps_;
493 PrintF("%d maps { ", list->size()); 434 PrintF("%d maps { ", list->size());
494 for (int j = 0; j < list->size(); j++) { 435 for (int j = 0; j < list->size(); j++) {
495 if (j > 0) PrintF(", "); 436 if (j > 0) PrintF(", ");
496 PrintF("%" V8PRIxPTR, list->at(j).Hashcode()); 437 PrintF("%" V8PRIxPTR, list->at(j).Hashcode());
497 } 438 }
498 PrintF(" }\n"); 439 PrintF(" }\n");
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 PRINT_STAT(removed_cho); 584 PRINT_STAT(removed_cho);
644 PRINT_STAT(narrowed); 585 PRINT_STAT(narrowed);
645 PRINT_STAT(loads); 586 PRINT_STAT(loads);
646 PRINT_STAT(empty); 587 PRINT_STAT(empty);
647 PRINT_STAT(compares_true); 588 PRINT_STAT(compares_true);
648 PRINT_STAT(compares_false); 589 PRINT_STAT(compares_false);
649 PRINT_STAT(transitions); 590 PRINT_STAT(transitions);
650 } 591 }
651 592
652 } } // namespace v8::internal 593 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/flag-definitions.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698