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

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

Issue 185653004: Experimental parser: merge to r19637 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 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-bce.cc ('k') | src/hydrogen-flow-engine.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 HValue* check_; // The last check instruction. 51 HInstruction* 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 datastructure 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 } 66 }
(...skipping 29 matching lines...) Expand all
96 case HValue::kCheckMapValue: { 96 case HValue::kCheckMapValue: {
97 ReduceCheckMapValue(HCheckMapValue::cast(instr)); 97 ReduceCheckMapValue(HCheckMapValue::cast(instr));
98 break; 98 break;
99 } 99 }
100 case HValue::kCheckHeapObject: { 100 case HValue::kCheckHeapObject: {
101 ReduceCheckHeapObject(HCheckHeapObject::cast(instr)); 101 ReduceCheckHeapObject(HCheckHeapObject::cast(instr));
102 break; 102 break;
103 } 103 }
104 default: { 104 default: {
105 // If the instruction changes maps uncontrollably, drop everything. 105 // If the instruction changes maps uncontrollably, drop everything.
106 if (instr->CheckGVNFlag(kChangesMaps) || 106 if (instr->CheckChangesFlag(kMaps) ||
107 instr->CheckGVNFlag(kChangesOsrEntries)) { 107 instr->CheckChangesFlag(kOsrEntries)) {
108 Kill(); 108 Kill();
109 } 109 }
110 } 110 }
111 // Improvements possible: 111 // Improvements possible:
112 // - eliminate redundant HCheckSmi, HCheckInstanceType instructions 112 // - eliminate redundant HCheckSmi, HCheckInstanceType instructions
113 // - track which values have been HCheckHeapObject'd 113 // - track which values have been HCheckHeapObject'd
114 } 114 }
115 115
116 return this; 116 return this;
117 } 117 }
118 118
119 // Global analysis: Copy state to successor block. 119 // Support for global analysis with HFlowEngine: Merge given state with
120 HCheckTable* Copy(HBasicBlock* succ, Zone* zone) { 120 // the other incoming state.
121 static HCheckTable* Merge(HCheckTable* succ_state, HBasicBlock* succ_block,
122 HCheckTable* pred_state, HBasicBlock* pred_block,
123 Zone* zone) {
124 if (pred_state == NULL || pred_block->IsUnreachable()) {
125 return succ_state;
126 }
127 if (succ_state == NULL) {
128 return pred_state->Copy(succ_block, pred_block, zone);
129 } else {
130 return succ_state->Merge(succ_block, pred_state, pred_block, zone);
131 }
132 }
133
134 // Support for global analysis with HFlowEngine: Given state merged with all
135 // the other incoming states, prepare it for use.
136 static HCheckTable* Finish(HCheckTable* state, HBasicBlock* block,
137 Zone* zone) {
138 if (state == NULL) {
139 block->MarkUnreachable();
140 } else if (block->IsUnreachable()) {
141 state = NULL;
142 }
143 if (FLAG_trace_check_elimination) {
144 PrintF("Processing B%d, checkmaps-table:\n", block->block_id());
145 Print(state);
146 }
147 return state;
148 }
149
150 private:
151 // Copy state to successor block.
152 HCheckTable* Copy(HBasicBlock* succ, HBasicBlock* from_block, Zone* zone) {
121 HCheckTable* copy = new(phase_->zone()) HCheckTable(phase_); 153 HCheckTable* copy = new(phase_->zone()) HCheckTable(phase_);
122 for (int i = 0; i < size_; i++) { 154 for (int i = 0; i < size_; i++) {
123 HCheckTableEntry* old_entry = &entries_[i]; 155 HCheckTableEntry* old_entry = &entries_[i];
156 ASSERT(old_entry->maps_->size() > 0);
124 HCheckTableEntry* new_entry = &copy->entries_[i]; 157 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_; 158 new_entry->object_ = old_entry->object_;
127 new_entry->check_ = NULL;
128 new_entry->maps_ = old_entry->maps_->Copy(phase_->zone()); 159 new_entry->maps_ = old_entry->maps_->Copy(phase_->zone());
160 // Keep the check if the existing check's block dominates the successor.
161 if (old_entry->check_ != NULL &&
162 old_entry->check_->block()->Dominates(succ)) {
163 new_entry->check_ = old_entry->check_;
164 } else {
165 // Leave it NULL till we meet a new check instruction for this object
166 // in the control flow.
167 new_entry->check_ = NULL;
168 }
129 } 169 }
130 copy->cursor_ = cursor_; 170 copy->cursor_ = cursor_;
131 copy->size_ = size_; 171 copy->size_ = size_;
132 172
173 // Create entries for succ block's phis.
174 if (!succ->IsLoopHeader() && succ->phis()->length() > 0) {
175 int pred_index = succ->PredecessorIndexOf(from_block);
176 for (int phi_index = 0;
177 phi_index < succ->phis()->length();
178 ++phi_index) {
179 HPhi* phi = succ->phis()->at(phi_index);
180 HValue* phi_operand = phi->OperandAt(pred_index);
181
182 HCheckTableEntry* pred_entry = copy->Find(phi_operand);
183 if (pred_entry != NULL) {
184 // Create an entry for a phi in the table.
185 copy->Insert(phi, NULL, pred_entry->maps_->Copy(phase_->zone()));
186 }
187 }
188 }
189
133 // Branch-sensitive analysis for certain comparisons may add more facts 190 // Branch-sensitive analysis for certain comparisons may add more facts
134 // to the state for the successor on the true branch. 191 // to the state for the successor on the true branch.
135 HControlInstruction* end = succ->predecessors()->at(0)->end(); 192 bool learned = false;
136 if (succ->predecessors()->length() == 1 && end->SuccessorAt(0) == succ) { 193 if (succ->predecessors()->length() == 1) {
194 HControlInstruction* end = succ->predecessors()->at(0)->end();
195 bool is_true_branch = end->SuccessorAt(0) == succ;
137 if (end->IsCompareMap()) { 196 if (end->IsCompareMap()) {
138 // Learn on the true branch of if(CompareMap(x)).
139 HCompareMap* cmp = HCompareMap::cast(end); 197 HCompareMap* cmp = HCompareMap::cast(end);
140 HValue* object = cmp->value()->ActualValue(); 198 HValue* object = cmp->value()->ActualValue();
141 HCheckTableEntry* entry = copy->Find(object); 199 HCheckTableEntry* entry = copy->Find(object);
142 if (entry == NULL) { 200 if (is_true_branch) {
143 copy->Insert(object, cmp->map()); 201 // Learn on the true branch of if(CompareMap(x)).
202 if (entry == NULL) {
203 copy->Insert(object, cmp, cmp->map());
204 } else {
205 MapSet list = new(phase_->zone()) UniqueSet<Map>();
206 list->Add(cmp->map(), phase_->zone());
207 entry->maps_ = list;
208 entry->check_ = cmp;
209 }
144 } else { 210 } else {
145 MapSet list = new(phase_->zone()) UniqueSet<Map>(); 211 // Learn on the false branch of if(CompareMap(x)).
146 list->Add(cmp->map(), phase_->zone()); 212 if (entry != NULL) {
147 entry->maps_ = list; 213 entry->maps_->Remove(cmp->map());
214 }
148 } 215 }
149 } else if (end->IsCompareObjectEqAndBranch()) { 216 learned = true;
217 } else if (is_true_branch && end->IsCompareObjectEqAndBranch()) {
150 // Learn on the true branch of if(CmpObjectEq(x, y)). 218 // Learn on the true branch of if(CmpObjectEq(x, y)).
151 HCompareObjectEqAndBranch* cmp = 219 HCompareObjectEqAndBranch* cmp =
152 HCompareObjectEqAndBranch::cast(end); 220 HCompareObjectEqAndBranch::cast(end);
153 HValue* left = cmp->left()->ActualValue(); 221 HValue* left = cmp->left()->ActualValue();
154 HValue* right = cmp->right()->ActualValue(); 222 HValue* right = cmp->right()->ActualValue();
155 HCheckTableEntry* le = copy->Find(left); 223 HCheckTableEntry* le = copy->Find(left);
156 HCheckTableEntry* re = copy->Find(right); 224 HCheckTableEntry* re = copy->Find(right);
157 if (le == NULL) { 225 if (le == NULL) {
158 if (re != NULL) { 226 if (re != NULL) {
159 copy->Insert(left, NULL, re->maps_->Copy(zone)); 227 copy->Insert(left, NULL, re->maps_->Copy(zone));
160 } 228 }
161 } else if (re == NULL) { 229 } else if (re == NULL) {
162 copy->Insert(right, NULL, le->maps_->Copy(zone)); 230 copy->Insert(right, NULL, le->maps_->Copy(zone));
163 } else { 231 } else {
164 MapSet intersect = le->maps_->Intersect(re->maps_, zone); 232 MapSet intersect = le->maps_->Intersect(re->maps_, zone);
165 le->maps_ = intersect; 233 le->maps_ = intersect;
166 re->maps_ = intersect->Copy(zone); 234 re->maps_ = intersect->Copy(zone);
167 } 235 }
236 learned = true;
168 } 237 }
169 // Learning on false branches requires storing negative facts. 238 // Learning on false branches requires storing negative facts.
170 } 239 }
171 240
241 if (FLAG_trace_check_elimination) {
242 PrintF("B%d checkmaps-table %s from B%d:\n",
243 succ->block_id(),
244 learned ? "learned" : "copied",
245 from_block->block_id());
246 Print(copy);
247 }
248
172 return copy; 249 return copy;
173 } 250 }
174 251
175 // Global analysis: Merge this state with the other incoming state. 252 // Merge this state with the other incoming state.
176 HCheckTable* Merge(HBasicBlock* succ, HCheckTable* that, Zone* zone) { 253 HCheckTable* Merge(HBasicBlock* succ, HCheckTable* that,
254 HBasicBlock* pred_block, Zone* zone) {
177 if (that->size_ == 0) { 255 if (that->size_ == 0) {
178 // If the other state is empty, simply reset. 256 // If the other state is empty, simply reset.
179 size_ = 0; 257 size_ = 0;
180 cursor_ = 0; 258 cursor_ = 0;
181 return this; 259 } else {
260 int pred_index = succ->PredecessorIndexOf(pred_block);
261 bool compact = false;
262 for (int i = 0; i < size_; i++) {
263 HCheckTableEntry* this_entry = &entries_[i];
264 HCheckTableEntry* that_entry;
265 if (this_entry->object_->IsPhi() &&
266 this_entry->object_->block() == succ) {
267 HPhi* phi = HPhi::cast(this_entry->object_);
268 HValue* phi_operand = phi->OperandAt(pred_index);
269 that_entry = that->Find(phi_operand);
270
271 } else {
272 that_entry = that->Find(this_entry->object_);
273 }
274
275 if (that_entry == NULL) {
276 this_entry->object_ = NULL;
277 compact = true;
278 } else {
279 this_entry->maps_ =
280 this_entry->maps_->Union(that_entry->maps_, phase_->zone());
281 if (this_entry->check_ != that_entry->check_) {
282 this_entry->check_ = NULL;
283 }
284 ASSERT(this_entry->maps_->size() > 0);
285 }
286 }
287 if (compact) Compact();
182 } 288 }
183 bool compact = false; 289
184 for (int i = 0; i < size_; i++) { 290 if (FLAG_trace_check_elimination) {
185 HCheckTableEntry* this_entry = &entries_[i]; 291 PrintF("B%d checkmaps-table merged with B%d table:\n",
186 HCheckTableEntry* that_entry = that->Find(this_entry->object_); 292 succ->block_id(), pred_block->block_id());
187 if (that_entry == NULL) { 293 Print(this);
188 this_entry->object_ = NULL;
189 compact = true;
190 } else {
191 this_entry->maps_ = this_entry->maps_->Union(
192 that_entry->maps_, phase_->zone());
193 if (this_entry->check_ != that_entry->check_) this_entry->check_ = NULL;
194 ASSERT(this_entry->maps_->size() > 0);
195 }
196 } 294 }
197 if (compact) Compact();
198 return this; 295 return this;
199 } 296 }
200 297
201 void ReduceCheckMaps(HCheckMaps* instr) { 298 void ReduceCheckMaps(HCheckMaps* instr) {
202 HValue* object = instr->value()->ActualValue(); 299 HValue* object = instr->value()->ActualValue();
203 HCheckTableEntry* entry = Find(object); 300 HCheckTableEntry* entry = Find(object);
204 if (entry != NULL) { 301 if (entry != NULL) {
205 // entry found; 302 // entry found;
206 MapSet a = entry->maps_; 303 MapSet a = entry->maps_;
207 MapSet i = instr->map_set().Copy(phase_->zone()); 304 MapSet i = instr->map_set().Copy(phase_->zone());
208 if (a->IsSubset(i)) { 305 if (a->IsSubset(i)) {
209 // The first check is more strict; the second is redundant. 306 // The first check is more strict; the second is redundant.
210 if (entry->check_ != NULL) { 307 if (entry->check_ != NULL) {
308 TRACE(("Replacing redundant CheckMaps #%d at B%d with #%d\n",
309 instr->id(), instr->block()->block_id(), entry->check_->id()));
211 instr->DeleteAndReplaceWith(entry->check_); 310 instr->DeleteAndReplaceWith(entry->check_);
212 INC_STAT(redundant_); 311 INC_STAT(redundant_);
213 } else { 312 } else {
214 instr->DeleteAndReplaceWith(instr->value()); 313 TRACE(("Marking redundant CheckMaps #%d at B%d as dead\n",
314 instr->id(), instr->block()->block_id()));
315 // Mark check as dead but leave it in the graph as a checkpoint for
316 // subsequent checks.
317 instr->SetFlag(HValue::kIsDead);
318 entry->check_ = instr;
215 INC_STAT(removed_); 319 INC_STAT(removed_);
216 } 320 }
217 return; 321 return;
218 } 322 }
219 i = i->Intersect(a, phase_->zone()); 323 MapSet intersection = i->Intersect(a, phase_->zone());
220 if (i->size() == 0) { 324 if (intersection->size() == 0) {
221 // Intersection is empty; probably megamorphic, which is likely to 325 // Intersection is empty; probably megamorphic, which is likely to
222 // deopt anyway, so just leave things as they are. 326 // deopt anyway, so just leave things as they are.
223 INC_STAT(empty_); 327 INC_STAT(empty_);
224 } else { 328 } else {
225 // TODO(titzer): replace the first check with a more strict check 329 // Update set of maps in the entry.
226 INC_STAT(narrowed_); 330 entry->maps_ = intersection;
331 if (intersection->size() != i->size()) {
332 // Narrow set of maps in the second check maps instruction.
333 HGraph* graph = instr->block()->graph();
334 if (entry->check_ != NULL &&
335 entry->check_->block() == instr->block() &&
336 entry->check_->IsCheckMaps()) {
337 // There is a check in the same block so replace it with a more
338 // strict check and eliminate the second check entirely.
339 HCheckMaps* check = HCheckMaps::cast(entry->check_);
340 TRACE(("CheckMaps #%d at B%d narrowed\n", check->id(),
341 check->block()->block_id()));
342 // Update map set and ensure that the check is alive.
343 check->set_map_set(intersection, graph->zone());
344 check->ClearFlag(HValue::kIsDead);
345 TRACE(("Replacing redundant CheckMaps #%d at B%d with #%d\n",
346 instr->id(), instr->block()->block_id(), entry->check_->id()));
347 instr->DeleteAndReplaceWith(entry->check_);
348 } else {
349 TRACE(("CheckMaps #%d at B%d narrowed\n", instr->id(),
350 instr->block()->block_id()));
351 instr->set_map_set(intersection, graph->zone());
352 entry->check_ = instr;
353 }
354
355 if (FLAG_trace_check_elimination) {
356 Print(this);
357 }
358 INC_STAT(narrowed_);
359 }
227 } 360 }
228 } else { 361 } else {
229 // No entry; insert a new one. 362 // No entry; insert a new one.
230 Insert(object, instr, instr->map_set().Copy(phase_->zone())); 363 Insert(object, instr, instr->map_set().Copy(phase_->zone()));
231 } 364 }
232 } 365 }
233 366
234 void ReduceCheckValue(HCheckValue* instr) { 367 void ReduceCheckValue(HCheckValue* instr) {
235 // Canonicalize HCheckValues; they might have their values load-eliminated. 368 // Canonicalize HCheckValues; they might have their values load-eliminated.
236 HValue* value = instr->Canonicalize(); 369 HValue* value = instr->Canonicalize();
(...skipping 20 matching lines...) Expand all
257 instr->DeleteAndReplaceWith(constant); 390 instr->DeleteAndReplaceWith(constant);
258 INC_STAT(loads_); 391 INC_STAT(loads_);
259 } 392 }
260 393
261 void ReduceCheckMapValue(HCheckMapValue* instr) { 394 void ReduceCheckMapValue(HCheckMapValue* instr) {
262 if (!instr->map()->IsConstant()) return; // Nothing to learn. 395 if (!instr->map()->IsConstant()) return; // Nothing to learn.
263 396
264 HValue* object = instr->value()->ActualValue(); 397 HValue* object = instr->value()->ActualValue();
265 // Match a HCheckMapValue(object, HConstant(map)) 398 // Match a HCheckMapValue(object, HConstant(map))
266 Unique<Map> map = MapConstant(instr->map()); 399 Unique<Map> map = MapConstant(instr->map());
267 MapSet maps = FindMaps(object); 400
268 if (maps != NULL) { 401 HCheckTableEntry* entry = Find(object);
402 if (entry != NULL) {
403 MapSet maps = entry->maps_;
269 if (maps->Contains(map)) { 404 if (maps->Contains(map)) {
270 if (maps->size() == 1) { 405 if (maps->size() == 1) {
271 // Object is known to have exactly this map. 406 // Object is known to have exactly this map.
272 instr->DeleteAndReplaceWith(NULL); 407 if (entry->check_ != NULL) {
408 instr->DeleteAndReplaceWith(entry->check_);
409 } else {
410 // Mark check as dead but leave it in the graph as a checkpoint for
411 // subsequent checks.
412 instr->SetFlag(HValue::kIsDead);
413 entry->check_ = instr;
414 }
273 INC_STAT(removed_); 415 INC_STAT(removed_);
274 } else { 416 } else {
275 // Only one map survives the check. 417 // Only one map survives the check.
276 maps->Clear(); 418 maps->Clear();
277 maps->Add(map, phase_->zone()); 419 maps->Add(map, phase_->zone());
420 entry->check_ = instr;
278 } 421 }
279 } 422 }
280 } else { 423 } else {
281 // No prior information. 424 // No prior information.
282 Insert(object, map); 425 Insert(object, instr, map);
283 } 426 }
284 } 427 }
285 428
286 void ReduceCheckHeapObject(HCheckHeapObject* instr) { 429 void ReduceCheckHeapObject(HCheckHeapObject* instr) {
287 if (FindMaps(instr->value()->ActualValue()) != NULL) { 430 if (FindMaps(instr->value()->ActualValue()) != NULL) {
288 // If the object has known maps, it's definitely a heap object. 431 // If the object has known maps, it's definitely a heap object.
289 instr->DeleteAndReplaceWith(instr->value()); 432 instr->DeleteAndReplaceWith(instr->value());
290 INC_STAT(removed_cho_); 433 INC_STAT(removed_cho_);
291 } 434 }
292 } 435 }
293 436
294 void ReduceStoreNamedField(HStoreNamedField* instr) { 437 void ReduceStoreNamedField(HStoreNamedField* instr) {
295 HValue* object = instr->object()->ActualValue(); 438 HValue* object = instr->object()->ActualValue();
296 if (instr->has_transition()) { 439 if (instr->has_transition()) {
297 // This store transitions the object to a new map. 440 // This store transitions the object to a new map.
298 Kill(object); 441 Kill(object);
299 Insert(object, MapConstant(instr->transition())); 442 Insert(object, NULL, MapConstant(instr->transition()));
300 } else if (IsMapAccess(instr->access())) { 443 } else if (IsMapAccess(instr->access())) {
301 // This is a store directly to the map field of the object. 444 // This is a store directly to the map field of the object.
302 Kill(object); 445 Kill(object);
303 if (!instr->value()->IsConstant()) return; 446 if (!instr->value()->IsConstant()) return;
304 Insert(object, MapConstant(instr->value())); 447 Insert(object, NULL, MapConstant(instr->value()));
305 } else { 448 } else {
306 // If the instruction changes maps, it should be handled above. 449 // If the instruction changes maps, it should be handled above.
307 CHECK(!instr->CheckGVNFlag(kChangesMaps)); 450 CHECK(!instr->CheckChangesFlag(kMaps));
308 } 451 }
309 } 452 }
310 453
311 void ReduceCompareMap(HCompareMap* instr) { 454 void ReduceCompareMap(HCompareMap* instr) {
312 MapSet maps = FindMaps(instr->value()->ActualValue()); 455 MapSet maps = FindMaps(instr->value()->ActualValue());
313 if (maps == NULL) return; 456 if (maps == NULL) return;
457
458 int succ;
314 if (maps->Contains(instr->map())) { 459 if (maps->Contains(instr->map())) {
315 if (maps->size() == 1) { 460 if (maps->size() != 1) {
316 // TODO(titzer): replace with goto true branch 461 TRACE(("CompareMap #%d for #%d at B%d can't be eliminated: "
317 INC_STAT(compares_true_); 462 "ambiguous set of maps\n", instr->id(), instr->value()->id(),
463 instr->block()->block_id()));
464 return;
318 } 465 }
466 succ = 0;
467 INC_STAT(compares_true_);
319 } else { 468 } else {
320 // TODO(titzer): replace with goto false branch 469 succ = 1;
321 INC_STAT(compares_false_); 470 INC_STAT(compares_false_);
322 } 471 }
472
473 TRACE(("Marking redundant CompareMap #%d for #%d at B%d as %s\n",
474 instr->id(), instr->value()->id(), instr->block()->block_id(),
475 succ == 0 ? "true" : "false"));
476 instr->set_known_successor_index(succ);
477
478 int unreachable_succ = 1 - succ;
479 instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
323 } 480 }
324 481
325 void ReduceTransitionElementsKind(HTransitionElementsKind* instr) { 482 void ReduceTransitionElementsKind(HTransitionElementsKind* instr) {
326 MapSet maps = FindMaps(instr->object()->ActualValue()); 483 MapSet maps = FindMaps(instr->object()->ActualValue());
327 // Can only learn more about an object that already has a known set of maps. 484 // Can only learn more about an object that already has a known set of maps.
328 if (maps == NULL) return; 485 if (maps == NULL) return;
329 if (maps->Contains(instr->original_map())) { 486 if (maps->Contains(instr->original_map())) {
330 // If the object has the original map, it will be transitioned. 487 // If the object has the original map, it will be transitioned.
331 maps->Remove(instr->original_map()); 488 maps->Remove(instr->original_map());
332 maps->Add(instr->transitioned_map(), phase_->zone()); 489 maps->Add(instr->transitioned_map(), phase_->zone());
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
383 int R = size_ - cursor_; 540 int R = size_ - cursor_;
384 541
385 OS::MemMove(&tmp_entries[0], &entries_[0], L * sizeof(HCheckTableEntry)); 542 OS::MemMove(&tmp_entries[0], &entries_[0], L * sizeof(HCheckTableEntry));
386 OS::MemMove(&entries_[0], &entries_[L], R * sizeof(HCheckTableEntry)); 543 OS::MemMove(&entries_[0], &entries_[L], R * sizeof(HCheckTableEntry));
387 OS::MemMove(&entries_[R], &tmp_entries[0], L * sizeof(HCheckTableEntry)); 544 OS::MemMove(&entries_[R], &tmp_entries[0], L * sizeof(HCheckTableEntry));
388 } 545 }
389 546
390 cursor_ = size_; // Move cursor to end. 547 cursor_ = size_; // Move cursor to end.
391 } 548 }
392 549
393 void Print() { 550 static void Print(HCheckTable* table) {
394 for (int i = 0; i < size_; i++) { 551 if (table == NULL) {
395 HCheckTableEntry* entry = &entries_[i]; 552 PrintF(" unreachable\n");
553 return;
554 }
555
556 for (int i = 0; i < table->size_; i++) {
557 HCheckTableEntry* entry = &table->entries_[i];
396 ASSERT(entry->object_ != NULL); 558 ASSERT(entry->object_ != NULL);
397 PrintF(" checkmaps-table @%d: object #%d ", i, entry->object_->id()); 559 PrintF(" checkmaps-table @%d: %s #%d ", i,
560 entry->object_->IsPhi() ? "phi" : "object", entry->object_->id());
398 if (entry->check_ != NULL) { 561 if (entry->check_ != NULL) {
399 PrintF("check #%d ", entry->check_->id()); 562 PrintF("check #%d ", entry->check_->id());
400 } 563 }
401 MapSet list = entry->maps_; 564 MapSet list = entry->maps_;
402 PrintF("%d maps { ", list->size()); 565 PrintF("%d maps { ", list->size());
403 for (int j = 0; j < list->size(); j++) { 566 for (int j = 0; j < list->size(); j++) {
404 if (j > 0) PrintF(", "); 567 if (j > 0) PrintF(", ");
405 PrintF("%" V8PRIxPTR, list->at(j).Hashcode()); 568 PrintF("%" V8PRIxPTR, list->at(j).Hashcode());
406 } 569 }
407 PrintF(" }\n"); 570 PrintF(" }\n");
408 } 571 }
409 } 572 }
410 573
411 private:
412 HCheckTableEntry* Find(HValue* object) { 574 HCheckTableEntry* Find(HValue* object) {
413 for (int i = size_ - 1; i >= 0; i--) { 575 for (int i = size_ - 1; i >= 0; i--) {
414 // Search from most-recently-inserted to least-recently-inserted. 576 // Search from most-recently-inserted to least-recently-inserted.
415 HCheckTableEntry* entry = &entries_[i]; 577 HCheckTableEntry* entry = &entries_[i];
416 ASSERT(entry->object_ != NULL); 578 ASSERT(entry->object_ != NULL);
417 if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry; 579 if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry;
418 } 580 }
419 return NULL; 581 return NULL;
420 } 582 }
421 583
422 MapSet FindMaps(HValue* object) { 584 MapSet FindMaps(HValue* object) {
423 HCheckTableEntry* entry = Find(object); 585 HCheckTableEntry* entry = Find(object);
424 return entry == NULL ? NULL : entry->maps_; 586 return entry == NULL ? NULL : entry->maps_;
425 } 587 }
426 588
427 void Insert(HValue* object, Unique<Map> map) { 589 void Insert(HValue* object, HInstruction* check, Unique<Map> map) {
428 MapSet list = new(phase_->zone()) UniqueSet<Map>(); 590 MapSet list = new(phase_->zone()) UniqueSet<Map>();
429 list->Add(map, phase_->zone()); 591 list->Add(map, phase_->zone());
430 Insert(object, NULL, list); 592 Insert(object, check, list);
431 } 593 }
432 594
433 void Insert(HValue* object, HCheckMaps* check, MapSet maps) { 595 void Insert(HValue* object, HInstruction* check, MapSet maps) {
434 HCheckTableEntry* entry = &entries_[cursor_++]; 596 HCheckTableEntry* entry = &entries_[cursor_++];
435 entry->object_ = object; 597 entry->object_ = object;
436 entry->check_ = check; 598 entry->check_ = check;
437 entry->maps_ = maps; 599 entry->maps_ = maps;
438 // If the table becomes full, wrap around and overwrite older entries. 600 // If the table becomes full, wrap around and overwrite older entries.
439 if (cursor_ == kMaxTrackedObjects) cursor_ = 0; 601 if (cursor_ == kMaxTrackedObjects) cursor_ = 0;
440 if (size_ < kMaxTrackedObjects) size_++; 602 if (size_ < kMaxTrackedObjects) size_++;
441 } 603 }
442 604
443 bool IsMapAccess(HObjectAccess access) { 605 bool IsMapAccess(HObjectAccess access) {
444 return access.IsInobject() && access.offset() == JSObject::kMapOffset; 606 return access.IsInobject() && access.offset() == JSObject::kMapOffset;
445 } 607 }
446 608
447 Unique<Map> MapConstant(HValue* value) { 609 Unique<Map> MapConstant(HValue* value) {
448 return Unique<Map>::cast(HConstant::cast(value)->GetUnique()); 610 return Unique<Map>::cast(HConstant::cast(value)->GetUnique());
449 } 611 }
450 612
451 friend class HCheckMapsEffects; 613 friend class HCheckMapsEffects;
614 friend class HCheckEliminationPhase;
452 615
453 HCheckEliminationPhase* phase_; 616 HCheckEliminationPhase* phase_;
454 HCheckTableEntry entries_[kMaxTrackedObjects]; 617 HCheckTableEntry entries_[kMaxTrackedObjects];
455 int16_t cursor_; // Must be <= kMaxTrackedObjects 618 int16_t cursor_; // Must be <= kMaxTrackedObjects
456 int16_t size_; // Must be <= kMaxTrackedObjects 619 int16_t size_; // Must be <= kMaxTrackedObjects
457 // TODO(titzer): STATIC_ASSERT kMaxTrackedObjects < max(cursor_) 620 // TODO(titzer): STATIC_ASSERT kMaxTrackedObjects < max(cursor_)
458 }; 621 };
459 622
460 623
461 // Collects instructions that can cause effects that invalidate information 624 // Collects instructions that can cause effects that invalidate information
(...skipping 13 matching lines...) Expand all
475 switch (instr->opcode()) { 638 switch (instr->opcode()) {
476 case HValue::kStoreNamedField: { 639 case HValue::kStoreNamedField: {
477 stores_.Add(HStoreNamedField::cast(instr), zone); 640 stores_.Add(HStoreNamedField::cast(instr), zone);
478 break; 641 break;
479 } 642 }
480 case HValue::kOsrEntry: { 643 case HValue::kOsrEntry: {
481 // Kill everything. Loads must not be hoisted past the OSR entry. 644 // Kill everything. Loads must not be hoisted past the OSR entry.
482 maps_stored_ = true; 645 maps_stored_ = true;
483 } 646 }
484 default: { 647 default: {
485 maps_stored_ |= (instr->CheckGVNFlag(kChangesMaps) | 648 maps_stored_ |= (instr->CheckChangesFlag(kMaps) |
486 instr->CheckGVNFlag(kChangesElementsKind)); 649 instr->CheckChangesFlag(kElementsKind));
487 } 650 }
488 } 651 }
489 } 652 }
490 653
491 // Apply these effects to the given check elimination table. 654 // Apply these effects to the given check elimination table.
492 void Apply(HCheckTable* table) { 655 void Apply(HCheckTable* table) {
493 if (maps_stored_) { 656 if (maps_stored_) {
494 // Uncontrollable map modifications; kill everything. 657 // Uncontrollable map modifications; kill everything.
495 table->Kill(); 658 table->Kill();
496 return; 659 return;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
552 PRINT_STAT(removed_cho); 715 PRINT_STAT(removed_cho);
553 PRINT_STAT(narrowed); 716 PRINT_STAT(narrowed);
554 PRINT_STAT(loads); 717 PRINT_STAT(loads);
555 PRINT_STAT(empty); 718 PRINT_STAT(empty);
556 PRINT_STAT(compares_true); 719 PRINT_STAT(compares_true);
557 PRINT_STAT(compares_false); 720 PRINT_STAT(compares_false);
558 PRINT_STAT(transitions); 721 PRINT_STAT(transitions);
559 } 722 }
560 723
561 } } // namespace v8::internal 724 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen-bce.cc ('k') | src/hydrogen-flow-engine.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698