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

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

Issue 140543004: More check elimination improvements including partial learning on false branches of CompareMap and … (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/hydrogen.cc ('k') | no next file » | 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 55
56 // The main data structure used during check elimination, which stores a 56 // The main data structure 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 unreachable_(false) {
66 } 67 }
67 68
68 // The main processing of instructions. 69 // The main processing of instructions.
69 HCheckTable* Process(HInstruction* instr, Zone* zone) { 70 HCheckTable* Process(HInstruction* instr, Zone* zone) {
70 switch (instr->opcode()) { 71 switch (instr->opcode()) {
71 case HValue::kCheckMaps: { 72 case HValue::kCheckMaps: {
72 ReduceCheckMaps(HCheckMaps::cast(instr)); 73 ReduceCheckMaps(HCheckMaps::cast(instr));
73 break; 74 break;
74 } 75 }
75 case HValue::kCheckValue: { 76 case HValue::kCheckValue: {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 // - eliminate redundant HCheckSmi, HCheckInstanceType instructions 113 // - eliminate redundant HCheckSmi, HCheckInstanceType instructions
113 // - track which values have been HCheckHeapObject'd 114 // - track which values have been HCheckHeapObject'd
114 } 115 }
115 116
116 return this; 117 return this;
117 } 118 }
118 119
119 // Global analysis: Copy state to successor block. 120 // Global analysis: Copy state to successor block.
120 HCheckTable* Copy(HBasicBlock* succ, HBasicBlock* from_block, Zone* zone) { 121 HCheckTable* Copy(HBasicBlock* succ, HBasicBlock* from_block, Zone* zone) {
121 HCheckTable* copy = new(phase_->zone()) HCheckTable(phase_); 122 HCheckTable* copy = new(phase_->zone()) HCheckTable(phase_);
123 if (from_block->IsUnreachable() || succ->IsUnreachable()) {
124 copy->unreachable_ = true;
125 return copy;
126 }
122 for (int i = 0; i < size_; i++) { 127 for (int i = 0; i < size_; i++) {
123 HCheckTableEntry* old_entry = &entries_[i]; 128 HCheckTableEntry* old_entry = &entries_[i];
124 HCheckTableEntry* new_entry = &copy->entries_[i]; 129 HCheckTableEntry* new_entry = &copy->entries_[i];
125 // TODO(titzer): keep the check if this block dominates the successor?
126 new_entry->object_ = old_entry->object_; 130 new_entry->object_ = old_entry->object_;
127 new_entry->check_ = NULL;
128 new_entry->maps_ = old_entry->maps_->Copy(phase_->zone()); 131 new_entry->maps_ = old_entry->maps_->Copy(phase_->zone());
132 // Keep the check if the existing check's block dominates the successor.
133 if (old_entry->check_ != NULL &&
134 old_entry->check_->block()->Dominates(succ)) {
135 new_entry->check_ = old_entry->check_;
136 } else {
137 // Leave it NULL till we meet a new check instruction for this object
138 // in the control flow.
139 new_entry->check_ = NULL;
140 }
129 } 141 }
130 copy->cursor_ = cursor_; 142 copy->cursor_ = cursor_;
131 copy->size_ = size_; 143 copy->size_ = size_;
132 144
133 // Create entries for succ block's phis. 145 // Create entries for succ block's phis.
134 if (succ->phis()->length() > 0) { 146 if (succ->phis()->length() > 0) {
135 int pred_index = succ->PredecessorIndexOf(from_block); 147 int pred_index = succ->PredecessorIndexOf(from_block);
136 for (int phi_index = 0; 148 for (int phi_index = 0;
137 phi_index < succ->phis()->length(); 149 phi_index < succ->phis()->length();
138 ++phi_index) { 150 ++phi_index) {
139 HPhi* phi = succ->phis()->at(phi_index); 151 HPhi* phi = succ->phis()->at(phi_index);
140 HValue* phi_operand = phi->OperandAt(pred_index); 152 HValue* phi_operand = phi->OperandAt(pred_index);
141 153
142 HCheckTableEntry* pred_entry = copy->Find(phi_operand); 154 HCheckTableEntry* pred_entry = copy->Find(phi_operand);
143 if (pred_entry != NULL) { 155 if (pred_entry != NULL) {
144 // Create an entry for a phi in the table. 156 // Create an entry for a phi in the table.
145 copy->Insert(phi, NULL, pred_entry->maps_->Copy(phase_->zone())); 157 copy->Insert(phi, NULL, pred_entry->maps_->Copy(phase_->zone()));
146 } 158 }
147 } 159 }
148 } 160 }
149 161
150 // Branch-sensitive analysis for certain comparisons may add more facts 162 // Branch-sensitive analysis for certain comparisons may add more facts
151 // to the state for the successor on the true branch. 163 // to the state for the successor on the true branch.
152 bool learned = false; 164 bool learned = false;
153 HControlInstruction* end = succ->predecessors()->at(0)->end(); 165 HBasicBlock* pred_block = succ->predecessors()->at(0);
154 if (succ->predecessors()->length() == 1 && end->SuccessorAt(0) == succ) { 166 HControlInstruction* end = pred_block->end();
167 if (pred_block->IsReachable() && succ->predecessors()->length() == 1) {
Toon Verwaest 2014/02/11 14:54:04 I think we shouldn't explicitly care about the num
168 bool is_true_branch = end->SuccessorAt(0) == succ;
155 if (end->IsCompareMap()) { 169 if (end->IsCompareMap()) {
156 // Learn on the true branch of if(CompareMap(x)).
157 HCompareMap* cmp = HCompareMap::cast(end); 170 HCompareMap* cmp = HCompareMap::cast(end);
158 HValue* object = cmp->value()->ActualValue(); 171 HValue* object = cmp->value()->ActualValue();
159 HCheckTableEntry* entry = copy->Find(object); 172 HCheckTableEntry* entry = copy->Find(object);
160 if (entry == NULL) { 173 if (is_true_branch) {
161 copy->Insert(object, cmp->map()); 174 // Learn on the true branch of if(CompareMap(x)).
175 if (entry == NULL) {
176 copy->Insert(object, cmp, cmp->map());
177 } else {
178 MapSet list = new(phase_->zone()) UniqueSet<Map>();
179 list->Add(cmp->map(), phase_->zone());
180 entry->maps_ = list;
181 entry->check_ = cmp;
182 }
162 } else { 183 } else {
163 MapSet list = new(phase_->zone()) UniqueSet<Map>(); 184 // Learn on the false branch of if(CompareMap(x)).
164 list->Add(cmp->map(), phase_->zone()); 185 if (entry != NULL) {
165 entry->maps_ = list; 186 entry->maps_->Remove(cmp->map());
187 }
166 } 188 }
167 learned = true; 189 learned = true;
168 } else if (end->IsCompareObjectEqAndBranch()) { 190 } else if (is_true_branch && end->IsCompareObjectEqAndBranch()) {
169 // Learn on the true branch of if(CmpObjectEq(x, y)). 191 // Learn on the true branch of if(CmpObjectEq(x, y)).
170 HCompareObjectEqAndBranch* cmp = 192 HCompareObjectEqAndBranch* cmp =
171 HCompareObjectEqAndBranch::cast(end); 193 HCompareObjectEqAndBranch::cast(end);
172 HValue* left = cmp->left()->ActualValue(); 194 HValue* left = cmp->left()->ActualValue();
173 HValue* right = cmp->right()->ActualValue(); 195 HValue* right = cmp->right()->ActualValue();
174 HCheckTableEntry* le = copy->Find(left); 196 HCheckTableEntry* le = copy->Find(left);
175 HCheckTableEntry* re = copy->Find(right); 197 HCheckTableEntry* re = copy->Find(right);
176 if (le == NULL) { 198 if (le == NULL) {
177 if (re != NULL) { 199 if (re != NULL) {
178 copy->Insert(left, NULL, re->maps_->Copy(zone)); 200 copy->Insert(left, NULL, re->maps_->Copy(zone));
(...skipping 17 matching lines...) Expand all
196 from_block->block_id()); 218 from_block->block_id());
197 copy->Print(); 219 copy->Print();
198 } 220 }
199 221
200 return copy; 222 return copy;
201 } 223 }
202 224
203 // Global analysis: Merge this state with the other incoming state. 225 // Global analysis: Merge this state with the other incoming state.
204 HCheckTable* Merge(HBasicBlock* succ, HCheckTable* that, 226 HCheckTable* Merge(HBasicBlock* succ, HCheckTable* that,
205 HBasicBlock* pred_block, Zone* zone) { 227 HBasicBlock* pred_block, Zone* zone) {
206 if (pred_block->IsReachable()) { 228 if (pred_block->IsUnreachable() || that->unreachable_) return this;
207 if (that->size_ == 0) { 229 if (unreachable_) {
208 // If the other state is empty, simply reset. 230 return that->Copy(succ, pred_block, zone);
209 size_ = 0; 231 }
210 cursor_ = 0;
211 } else {
212 int pred_index = succ->PredecessorIndexOf(pred_block);
213 bool compact = false;
214 for (int i = 0; i < size_; i++) {
215 HCheckTableEntry* this_entry = &entries_[i];
216 HCheckTableEntry* that_entry;
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 232
223 } else { 233 if (that->size_ == 0) {
224 that_entry = that->Find(this_entry->object_); 234 // If the other state is empty, simply reset.
235 size_ = 0;
236 cursor_ = 0;
237 } else {
238 int pred_index = succ->PredecessorIndexOf(pred_block);
239 bool compact = false;
240 for (int i = 0; i < size_; i++) {
241 HCheckTableEntry* this_entry = &entries_[i];
242 HCheckTableEntry* that_entry;
243 if (this_entry->object_->IsPhi() &&
244 this_entry->object_->block() == succ) {
245 HPhi* phi = HPhi::cast(this_entry->object_);
246 HValue* phi_operand = phi->OperandAt(pred_index);
247 that_entry = that->Find(phi_operand);
248
249 } else {
250 that_entry = that->Find(this_entry->object_);
251 }
252
253 if (that_entry == NULL) {
254 this_entry->object_ = NULL;
255 compact = true;
256 } else {
257 this_entry->maps_ =
258 this_entry->maps_->Union(that_entry->maps_, phase_->zone());
259 if (this_entry->check_ != that_entry->check_) {
260 this_entry->check_ = NULL;
225 } 261 }
262 ASSERT(this_entry->maps_->size() > 0);
263 }
264 }
265 if (compact) Compact();
266 }
226 267
227 if (that_entry == NULL) {
228 this_entry->object_ = NULL;
229 compact = true;
230 } else {
231 this_entry->maps_ =
232 this_entry->maps_->Union(that_entry->maps_, phase_->zone());
233 if (this_entry->check_ != that_entry->check_) {
234 this_entry->check_ = NULL;
235 }
236 ASSERT(this_entry->maps_->size() > 0);
237 }
238 }
239 if (compact) Compact();
240 }
241 }
242 if (FLAG_trace_check_elimination) { 268 if (FLAG_trace_check_elimination) {
243 PrintF("B%d checkmaps-table merged with B%d table:\n", 269 PrintF("B%d checkmaps-table merged with B%d table:\n",
244 succ->block_id(), pred_block->block_id()); 270 succ->block_id(), pred_block->block_id());
245 Print(); 271 Print();
246 } 272 }
247 return this; 273 return this;
248 } 274 }
249 275
250 void ReduceCheckMaps(HCheckMaps* instr) { 276 void ReduceCheckMaps(HCheckMaps* instr) {
251 HValue* object = instr->value()->ActualValue(); 277 HValue* object = instr->value()->ActualValue();
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
342 instr->DeleteAndReplaceWith(constant); 368 instr->DeleteAndReplaceWith(constant);
343 INC_STAT(loads_); 369 INC_STAT(loads_);
344 } 370 }
345 371
346 void ReduceCheckMapValue(HCheckMapValue* instr) { 372 void ReduceCheckMapValue(HCheckMapValue* instr) {
347 if (!instr->map()->IsConstant()) return; // Nothing to learn. 373 if (!instr->map()->IsConstant()) return; // Nothing to learn.
348 374
349 HValue* object = instr->value()->ActualValue(); 375 HValue* object = instr->value()->ActualValue();
350 // Match a HCheckMapValue(object, HConstant(map)) 376 // Match a HCheckMapValue(object, HConstant(map))
351 Unique<Map> map = MapConstant(instr->map()); 377 Unique<Map> map = MapConstant(instr->map());
352 MapSet maps = FindMaps(object); 378
353 if (maps != NULL) { 379 HCheckTableEntry* entry = Find(object);
380 if (entry != NULL) {
381 MapSet maps = entry->maps_;
354 if (maps->Contains(map)) { 382 if (maps->Contains(map)) {
355 if (maps->size() == 1) { 383 if (maps->size() == 1) {
356 // Object is known to have exactly this map. 384 // Object is known to have exactly this map.
357 instr->DeleteAndReplaceWith(NULL); 385 if (entry->check_ != NULL) {
386 instr->DeleteAndReplaceWith(entry->check_);
387 } else {
388 // Mark check as dead but leave it in the graph as a checkpoint for
389 // subsequent checks.
390 instr->SetFlag(HValue::kIsDead);
391 entry->check_ = instr;
392 }
358 INC_STAT(removed_); 393 INC_STAT(removed_);
359 } else { 394 } else {
360 // Only one map survives the check. 395 // Only one map survives the check.
361 maps->Clear(); 396 maps->Clear();
362 maps->Add(map, phase_->zone()); 397 maps->Add(map, phase_->zone());
398 entry->check_ = instr;
363 } 399 }
364 } 400 }
365 } else { 401 } else {
366 // No prior information. 402 // No prior information.
367 Insert(object, map); 403 Insert(object, instr, map);
368 } 404 }
369 } 405 }
370 406
371 void ReduceCheckHeapObject(HCheckHeapObject* instr) { 407 void ReduceCheckHeapObject(HCheckHeapObject* instr) {
372 if (FindMaps(instr->value()->ActualValue()) != NULL) { 408 if (FindMaps(instr->value()->ActualValue()) != NULL) {
373 // If the object has known maps, it's definitely a heap object. 409 // If the object has known maps, it's definitely a heap object.
374 instr->DeleteAndReplaceWith(instr->value()); 410 instr->DeleteAndReplaceWith(instr->value());
375 INC_STAT(removed_cho_); 411 INC_STAT(removed_cho_);
376 } 412 }
377 } 413 }
378 414
379 void ReduceStoreNamedField(HStoreNamedField* instr) { 415 void ReduceStoreNamedField(HStoreNamedField* instr) {
380 HValue* object = instr->object()->ActualValue(); 416 HValue* object = instr->object()->ActualValue();
381 if (instr->has_transition()) { 417 if (instr->has_transition()) {
382 // This store transitions the object to a new map. 418 // This store transitions the object to a new map.
383 Kill(object); 419 Kill(object);
384 Insert(object, MapConstant(instr->transition())); 420 Insert(object, NULL, MapConstant(instr->transition()));
385 } else if (IsMapAccess(instr->access())) { 421 } else if (IsMapAccess(instr->access())) {
386 // This is a store directly to the map field of the object. 422 // This is a store directly to the map field of the object.
387 Kill(object); 423 Kill(object);
388 if (!instr->value()->IsConstant()) return; 424 if (!instr->value()->IsConstant()) return;
389 Insert(object, MapConstant(instr->value())); 425 Insert(object, NULL, MapConstant(instr->value()));
390 } else { 426 } else {
391 // If the instruction changes maps, it should be handled above. 427 // If the instruction changes maps, it should be handled above.
392 CHECK(!instr->CheckGVNFlag(kChangesMaps)); 428 CHECK(!instr->CheckGVNFlag(kChangesMaps));
393 } 429 }
394 } 430 }
395 431
396 void ReduceCompareMap(HCompareMap* instr) { 432 void ReduceCompareMap(HCompareMap* instr) {
397 MapSet maps = FindMaps(instr->value()->ActualValue()); 433 MapSet maps = FindMaps(instr->value()->ActualValue());
398 if (maps == NULL) return; 434 if (maps == NULL) return;
435
436 TRACE(("CompareMap for #%d at B%d ",
437 instr->value()->ActualValue()->id(), instr->block()->block_id()));
438
439 int succ;
399 if (maps->Contains(instr->map())) { 440 if (maps->Contains(instr->map())) {
400 if (maps->size() == 1) { 441 if (maps->size() != 1) {
401 TRACE(("Marking redundant CompareMap #%d at B%d as true\n", 442 TRACE(("can't be replaced with goto: ambiguous set of maps\n"));
402 instr->id(), instr->block()->block_id())); 443 return;
403 instr->set_known_successor_index(0);
404 INC_STAT(compares_true_);
405 } 444 }
445 succ = 0;
446 INC_STAT(compares_true_);
406 } else { 447 } else {
407 TRACE(("Marking redundant CompareMap #%d at B%d as false\n", 448 succ = 1;
408 instr->id(), instr->block()->block_id()));
409 instr->set_known_successor_index(1);
410 INC_STAT(compares_false_); 449 INC_STAT(compares_false_);
411 } 450 }
451
452 TRACE(("Marking redundant CompareMap #%d at B%d as %s\n",
453 instr->id(), instr->block()->block_id(), succ == 0 ? "true" : "false"));
454 instr->set_known_successor_index(succ);
455
456 int unreachable_succ = 1 - succ;
457 instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
412 } 458 }
413 459
414 void ReduceTransitionElementsKind(HTransitionElementsKind* instr) { 460 void ReduceTransitionElementsKind(HTransitionElementsKind* instr) {
415 MapSet maps = FindMaps(instr->object()->ActualValue()); 461 MapSet maps = FindMaps(instr->object()->ActualValue());
416 // Can only learn more about an object that already has a known set of maps. 462 // Can only learn more about an object that already has a known set of maps.
417 if (maps == NULL) return; 463 if (maps == NULL) return;
418 if (maps->Contains(instr->original_map())) { 464 if (maps->Contains(instr->original_map())) {
419 // If the object has the original map, it will be transitioned. 465 // If the object has the original map, it will be transitioned.
420 maps->Remove(instr->original_map()); 466 maps->Remove(instr->original_map());
421 maps->Add(instr->transitioned_map(), phase_->zone()); 467 maps->Add(instr->transitioned_map(), phase_->zone());
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 519
474 OS::MemMove(&tmp_entries[0], &entries_[0], L * sizeof(HCheckTableEntry)); 520 OS::MemMove(&tmp_entries[0], &entries_[0], L * sizeof(HCheckTableEntry));
475 OS::MemMove(&entries_[0], &entries_[L], R * sizeof(HCheckTableEntry)); 521 OS::MemMove(&entries_[0], &entries_[L], R * sizeof(HCheckTableEntry));
476 OS::MemMove(&entries_[R], &tmp_entries[0], L * sizeof(HCheckTableEntry)); 522 OS::MemMove(&entries_[R], &tmp_entries[0], L * sizeof(HCheckTableEntry));
477 } 523 }
478 524
479 cursor_ = size_; // Move cursor to end. 525 cursor_ = size_; // Move cursor to end.
480 } 526 }
481 527
482 void Print() { 528 void Print() {
529 if (unreachable_) {
530 PrintF(" checkmaps-table: unreachable\n");
531 return;
532 }
483 for (int i = 0; i < size_; i++) { 533 for (int i = 0; i < size_; i++) {
484 HCheckTableEntry* entry = &entries_[i]; 534 HCheckTableEntry* entry = &entries_[i];
485 ASSERT(entry->object_ != NULL); 535 ASSERT(entry->object_ != NULL);
486 PrintF(" checkmaps-table @%d: %s #%d ", i, 536 PrintF(" checkmaps-table @%d: %s #%d ", i,
487 entry->object_->IsPhi() ? "phi" : "object", 537 entry->object_->IsPhi() ? "phi" : "object", entry->object_->id());
488 entry->object_->id());
489 if (entry->check_ != NULL) { 538 if (entry->check_ != NULL) {
490 PrintF("check #%d ", entry->check_->id()); 539 PrintF("check #%d ", entry->check_->id());
491 } 540 }
492 MapSet list = entry->maps_; 541 MapSet list = entry->maps_;
493 PrintF("%d maps { ", list->size()); 542 PrintF("%d maps { ", list->size());
494 for (int j = 0; j < list->size(); j++) { 543 for (int j = 0; j < list->size(); j++) {
495 if (j > 0) PrintF(", "); 544 if (j > 0) PrintF(", ");
496 PrintF("%" V8PRIxPTR, list->at(j).Hashcode()); 545 PrintF("%" V8PRIxPTR, list->at(j).Hashcode());
497 } 546 }
498 PrintF(" }\n"); 547 PrintF(" }\n");
499 } 548 }
500 } 549 }
501 550
502 private: 551 private:
503 HCheckTableEntry* Find(HValue* object) { 552 HCheckTableEntry* Find(HValue* object) {
504 for (int i = size_ - 1; i >= 0; i--) { 553 for (int i = size_ - 1; i >= 0; i--) {
505 // Search from most-recently-inserted to least-recently-inserted. 554 // Search from most-recently-inserted to least-recently-inserted.
506 HCheckTableEntry* entry = &entries_[i]; 555 HCheckTableEntry* entry = &entries_[i];
507 ASSERT(entry->object_ != NULL); 556 ASSERT(entry->object_ != NULL);
508 if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry; 557 if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry;
509 } 558 }
510 return NULL; 559 return NULL;
511 } 560 }
512 561
513 MapSet FindMaps(HValue* object) { 562 MapSet FindMaps(HValue* object) {
514 HCheckTableEntry* entry = Find(object); 563 HCheckTableEntry* entry = Find(object);
515 return entry == NULL ? NULL : entry->maps_; 564 return entry == NULL ? NULL : entry->maps_;
516 } 565 }
517 566
518 void Insert(HValue* object, Unique<Map> map) { 567 void Insert(HValue* object, HInstruction* check, Unique<Map> map) {
519 MapSet list = new(phase_->zone()) UniqueSet<Map>(); 568 MapSet list = new(phase_->zone()) UniqueSet<Map>();
520 list->Add(map, phase_->zone()); 569 list->Add(map, phase_->zone());
521 Insert(object, NULL, list); 570 Insert(object, check, list);
522 } 571 }
523 572
524 void Insert(HValue* object, HCheckMaps* check, MapSet maps) { 573 void Insert(HValue* object, HInstruction* check, MapSet maps) {
525 HCheckTableEntry* entry = &entries_[cursor_++]; 574 HCheckTableEntry* entry = &entries_[cursor_++];
526 entry->object_ = object; 575 entry->object_ = object;
527 entry->check_ = check; 576 entry->check_ = check;
528 entry->maps_ = maps; 577 entry->maps_ = maps;
529 // If the table becomes full, wrap around and overwrite older entries. 578 // If the table becomes full, wrap around and overwrite older entries.
530 if (cursor_ == kMaxTrackedObjects) cursor_ = 0; 579 if (cursor_ == kMaxTrackedObjects) cursor_ = 0;
531 if (size_ < kMaxTrackedObjects) size_++; 580 if (size_ < kMaxTrackedObjects) size_++;
532 } 581 }
533 582
534 bool IsMapAccess(HObjectAccess access) { 583 bool IsMapAccess(HObjectAccess access) {
535 return access.IsInobject() && access.offset() == JSObject::kMapOffset; 584 return access.IsInobject() && access.offset() == JSObject::kMapOffset;
536 } 585 }
537 586
538 Unique<Map> MapConstant(HValue* value) { 587 Unique<Map> MapConstant(HValue* value) {
539 return Unique<Map>::cast(HConstant::cast(value)->GetUnique()); 588 return Unique<Map>::cast(HConstant::cast(value)->GetUnique());
540 } 589 }
541 590
542 friend class HCheckMapsEffects; 591 friend class HCheckMapsEffects;
543 592
544 HCheckEliminationPhase* phase_; 593 HCheckEliminationPhase* phase_;
545 HCheckTableEntry entries_[kMaxTrackedObjects]; 594 HCheckTableEntry entries_[kMaxTrackedObjects];
546 int16_t cursor_; // Must be <= kMaxTrackedObjects 595 int16_t cursor_; // Must be <= kMaxTrackedObjects
547 int16_t size_; // Must be <= kMaxTrackedObjects 596 int16_t size_; // Must be <= kMaxTrackedObjects
548 // TODO(titzer): STATIC_ASSERT kMaxTrackedObjects < max(cursor_) 597 // TODO(titzer): STATIC_ASSERT kMaxTrackedObjects < max(cursor_)
598 bool unreachable_;
549 }; 599 };
550 600
551 601
552 // Collects instructions that can cause effects that invalidate information 602 // Collects instructions that can cause effects that invalidate information
553 // needed for check elimination. 603 // needed for check elimination.
554 class HCheckMapsEffects : public ZoneObject { 604 class HCheckMapsEffects : public ZoneObject {
555 public: 605 public:
556 explicit HCheckMapsEffects(Zone* zone) 606 explicit HCheckMapsEffects(Zone* zone)
557 : maps_stored_(false), 607 : maps_stored_(false),
558 stores_(5, zone) { } 608 stores_(5, zone) { }
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
643 PRINT_STAT(removed_cho); 693 PRINT_STAT(removed_cho);
644 PRINT_STAT(narrowed); 694 PRINT_STAT(narrowed);
645 PRINT_STAT(loads); 695 PRINT_STAT(loads);
646 PRINT_STAT(empty); 696 PRINT_STAT(empty);
647 PRINT_STAT(compares_true); 697 PRINT_STAT(compares_true);
648 PRINT_STAT(compares_false); 698 PRINT_STAT(compares_false);
649 PRINT_STAT(transitions); 699 PRINT_STAT(transitions);
650 } 700 }
651 701
652 } } // namespace v8::internal 702 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698