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

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

Issue 181453002: Reset trunk to 3.24.35.4 (Closed) Base URL: https://v8.googlecode.com/svn/trunk
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-instructions.cc ('k') | src/hydrogen-representation-changes.cc » ('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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 s->object()->ActualValue()->id(), 93 s->object()->ActualValue()->id(),
94 s->value()->id())); 94 s->value()->id()));
95 HValue* result = store(s); 95 HValue* result = store(s);
96 if (result == NULL) { 96 if (result == NULL) {
97 // The store is redundant. Remove it. 97 // The store is redundant. Remove it.
98 TRACE((" remove S%d\n", instr->id())); 98 TRACE((" remove S%d\n", instr->id()));
99 instr->DeleteAndReplaceWith(NULL); 99 instr->DeleteAndReplaceWith(NULL);
100 } 100 }
101 break; 101 break;
102 } 102 }
103 case HValue::kTransitionElementsKind: {
104 HTransitionElementsKind* t = HTransitionElementsKind::cast(instr);
105 HValue* object = t->object()->ActualValue();
106 KillFieldInternal(object, FieldOf(JSArray::kElementsOffset), NULL);
107 KillFieldInternal(object, FieldOf(JSObject::kMapOffset), NULL);
108 break;
109 }
110 default: { 103 default: {
111 if (instr->CheckChangesFlag(kInobjectFields)) { 104 if (instr->CheckGVNFlag(kChangesInobjectFields)) {
112 TRACE((" kill-all i%d\n", instr->id())); 105 TRACE((" kill-all i%d\n", instr->id()));
113 Kill(); 106 Kill();
114 break; 107 break;
115 } 108 }
116 if (instr->CheckChangesFlag(kMaps)) { 109 if (instr->CheckGVNFlag(kChangesMaps)) {
117 TRACE((" kill-maps i%d\n", instr->id())); 110 TRACE((" kill-maps i%d\n", instr->id()));
118 KillOffset(JSObject::kMapOffset); 111 KillOffset(JSObject::kMapOffset);
119 } 112 }
120 if (instr->CheckChangesFlag(kElementsKind)) { 113 if (instr->CheckGVNFlag(kChangesElementsKind)) {
121 TRACE((" kill-elements-kind i%d\n", instr->id())); 114 TRACE((" kill-elements-kind i%d\n", instr->id()));
122 KillOffset(JSObject::kMapOffset); 115 KillOffset(JSObject::kMapOffset);
123 KillOffset(JSObject::kElementsOffset); 116 KillOffset(JSObject::kElementsOffset);
124 } 117 }
125 if (instr->CheckChangesFlag(kElementsPointer)) { 118 if (instr->CheckGVNFlag(kChangesElementsPointer)) {
126 TRACE((" kill-elements i%d\n", instr->id())); 119 TRACE((" kill-elements i%d\n", instr->id()));
127 KillOffset(JSObject::kElementsOffset); 120 KillOffset(JSObject::kElementsOffset);
128 } 121 }
129 if (instr->CheckChangesFlag(kOsrEntries)) { 122 if (instr->CheckGVNFlag(kChangesOsrEntries)) {
130 TRACE((" kill-osr i%d\n", instr->id())); 123 TRACE((" kill-osr i%d\n", instr->id()));
131 Kill(); 124 Kill();
132 } 125 }
133 } 126 }
134 // Improvements possible: 127 // Improvements possible:
135 // - learn from HCheckMaps for field 0 128 // - learn from HCheckMaps for field 0
136 // - remove unobservable stores (write-after-write) 129 // - remove unobservable stores (write-after-write)
137 // - track cells 130 // - track cells
138 // - track globals 131 // - track globals
139 // - track roots 132 // - track roots
140 } 133 }
141 return this; 134 return this;
142 } 135 }
143 136
144 // Support for global analysis with HFlowEngine: Merge given state with 137 // Support for global analysis with HFlowEngine: Copy state to successor
145 // the other incoming state. 138 // block.
146 static HLoadEliminationTable* Merge(HLoadEliminationTable* succ_state,
147 HBasicBlock* succ_block,
148 HLoadEliminationTable* pred_state,
149 HBasicBlock* pred_block,
150 Zone* zone) {
151 ASSERT(pred_state != NULL);
152 if (succ_state == NULL) {
153 return pred_state->Copy(succ_block, pred_block, zone);
154 } else {
155 return succ_state->Merge(succ_block, pred_state, pred_block, zone);
156 }
157 }
158
159 // Support for global analysis with HFlowEngine: Given state merged with all
160 // the other incoming states, prepare it for use.
161 static HLoadEliminationTable* Finish(HLoadEliminationTable* state,
162 HBasicBlock* block,
163 Zone* zone) {
164 ASSERT(state != NULL);
165 return state;
166 }
167
168 private:
169 // Copy state to successor block.
170 HLoadEliminationTable* Copy(HBasicBlock* succ, HBasicBlock* from_block, 139 HLoadEliminationTable* Copy(HBasicBlock* succ, HBasicBlock* from_block,
171 Zone* zone) { 140 Zone* zone) {
172 HLoadEliminationTable* copy = 141 HLoadEliminationTable* copy =
173 new(zone) HLoadEliminationTable(zone, aliasing_); 142 new(zone) HLoadEliminationTable(zone, aliasing_);
174 copy->EnsureFields(fields_.length()); 143 copy->EnsureFields(fields_.length());
175 for (int i = 0; i < fields_.length(); i++) { 144 for (int i = 0; i < fields_.length(); i++) {
176 copy->fields_[i] = fields_[i]->Copy(zone); 145 copy->fields_[i] = fields_[i]->Copy(zone);
177 } 146 }
178 if (FLAG_trace_load_elimination) { 147 if (FLAG_trace_load_elimination) {
179 TRACE((" copy-to B%d\n", succ->block_id())); 148 TRACE((" copy-to B%d\n", succ->block_id()));
180 copy->Print(); 149 copy->Print();
181 } 150 }
182 return copy; 151 return copy;
183 } 152 }
184 153
185 // Merge this state with the other incoming state. 154 // Support for global analysis with HFlowEngine: Merge this state with
155 // the other incoming state.
186 HLoadEliminationTable* Merge(HBasicBlock* succ, HLoadEliminationTable* that, 156 HLoadEliminationTable* Merge(HBasicBlock* succ, HLoadEliminationTable* that,
187 HBasicBlock* that_block, Zone* zone) { 157 HBasicBlock* that_block, Zone* zone) {
188 if (that->fields_.length() < fields_.length()) { 158 if (that->fields_.length() < fields_.length()) {
189 // Drop fields not in the other table. 159 // Drop fields not in the other table.
190 fields_.Rewind(that->fields_.length()); 160 fields_.Rewind(that->fields_.length());
191 } 161 }
192 for (int i = 0; i < fields_.length(); i++) { 162 for (int i = 0; i < fields_.length(); i++) {
193 // Merge the field approximations for like fields. 163 // Merge the field approximations for like fields.
194 HFieldApproximation* approx = fields_[i]; 164 HFieldApproximation* approx = fields_[i];
195 HFieldApproximation* prev = NULL; 165 HFieldApproximation* prev = NULL;
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
455 Zone* zone_; 425 Zone* zone_;
456 ZoneList<HFieldApproximation*> fields_; 426 ZoneList<HFieldApproximation*> fields_;
457 HAliasAnalyzer* aliasing_; 427 HAliasAnalyzer* aliasing_;
458 }; 428 };
459 429
460 430
461 // Support for HFlowEngine: collect store effects within loops. 431 // Support for HFlowEngine: collect store effects within loops.
462 class HLoadEliminationEffects : public ZoneObject { 432 class HLoadEliminationEffects : public ZoneObject {
463 public: 433 public:
464 explicit HLoadEliminationEffects(Zone* zone) 434 explicit HLoadEliminationEffects(Zone* zone)
465 : zone_(zone), stores_(5, zone) { } 435 : zone_(zone),
436 maps_stored_(false),
437 fields_stored_(false),
438 elements_stored_(false),
439 stores_(5, zone) { }
466 440
467 inline bool Disabled() { 441 inline bool Disabled() {
468 return false; // Effects are _not_ disabled. 442 return false; // Effects are _not_ disabled.
469 } 443 }
470 444
471 // Process a possibly side-effecting instruction. 445 // Process a possibly side-effecting instruction.
472 void Process(HInstruction* instr, Zone* zone) { 446 void Process(HInstruction* instr, Zone* zone) {
473 if (instr->IsStoreNamedField()) { 447 switch (instr->opcode()) {
474 stores_.Add(HStoreNamedField::cast(instr), zone_); 448 case HValue::kStoreNamedField: {
475 } else { 449 stores_.Add(HStoreNamedField::cast(instr), zone_);
476 flags_.Add(instr->ChangesFlags()); 450 break;
451 }
452 case HValue::kOsrEntry: {
453 // Kill everything. Loads must not be hoisted past the OSR entry.
454 maps_stored_ = true;
455 fields_stored_ = true;
456 elements_stored_ = true;
457 }
458 default: {
459 fields_stored_ |= instr->CheckGVNFlag(kChangesInobjectFields);
460 maps_stored_ |= instr->CheckGVNFlag(kChangesMaps);
461 maps_stored_ |= instr->CheckGVNFlag(kChangesElementsKind);
462 elements_stored_ |= instr->CheckGVNFlag(kChangesElementsKind);
463 elements_stored_ |= instr->CheckGVNFlag(kChangesElementsPointer);
464 }
477 } 465 }
478 } 466 }
479 467
480 // Apply these effects to the given load elimination table. 468 // Apply these effects to the given load elimination table.
481 void Apply(HLoadEliminationTable* table) { 469 void Apply(HLoadEliminationTable* table) {
482 // Loads must not be hoisted past the OSR entry, therefore we kill 470 if (fields_stored_) {
483 // everything if we see an OSR entry.
484 if (flags_.Contains(kInobjectFields) || flags_.Contains(kOsrEntries)) {
485 table->Kill(); 471 table->Kill();
486 return; 472 return;
487 } 473 }
488 if (flags_.Contains(kElementsKind) || flags_.Contains(kMaps)) { 474 if (maps_stored_) {
489 table->KillOffset(JSObject::kMapOffset); 475 table->KillOffset(JSObject::kMapOffset);
490 } 476 }
491 if (flags_.Contains(kElementsKind) || flags_.Contains(kElementsPointer)) { 477 if (elements_stored_) {
492 table->KillOffset(JSObject::kElementsOffset); 478 table->KillOffset(JSObject::kElementsOffset);
493 } 479 }
494 480
495 // Kill non-agreeing fields for each store contained in these effects. 481 // Kill non-agreeing fields for each store contained in these effects.
496 for (int i = 0; i < stores_.length(); i++) { 482 for (int i = 0; i < stores_.length(); i++) {
497 table->KillStore(stores_[i]); 483 table->KillStore(stores_[i]);
498 } 484 }
499 } 485 }
500 486
501 // Union these effects with the other effects. 487 // Union these effects with the other effects.
502 void Union(HLoadEliminationEffects* that, Zone* zone) { 488 void Union(HLoadEliminationEffects* that, Zone* zone) {
503 flags_.Add(that->flags_); 489 maps_stored_ |= that->maps_stored_;
490 fields_stored_ |= that->fields_stored_;
491 elements_stored_ |= that->elements_stored_;
504 for (int i = 0; i < that->stores_.length(); i++) { 492 for (int i = 0; i < that->stores_.length(); i++) {
505 stores_.Add(that->stores_[i], zone); 493 stores_.Add(that->stores_[i], zone);
506 } 494 }
507 } 495 }
508 496
509 private: 497 private:
510 Zone* zone_; 498 Zone* zone_;
511 GVNFlagSet flags_; 499 bool maps_stored_ : 1;
500 bool fields_stored_ : 1;
501 bool elements_stored_ : 1;
512 ZoneList<HStoreNamedField*> stores_; 502 ZoneList<HStoreNamedField*> stores_;
513 }; 503 };
514 504
515 505
516 // The main routine of the analysis phase. Use the HFlowEngine for either a 506 // The main routine of the analysis phase. Use the HFlowEngine for either a
517 // local or a global analysis. 507 // local or a global analysis.
518 void HLoadEliminationPhase::Run() { 508 void HLoadEliminationPhase::Run() {
519 HFlowEngine<HLoadEliminationTable, HLoadEliminationEffects> 509 HFlowEngine<HLoadEliminationTable, HLoadEliminationEffects>
520 engine(graph(), zone()); 510 engine(graph(), zone());
521 HAliasAnalyzer aliasing; 511 HAliasAnalyzer aliasing;
522 HLoadEliminationTable* table = 512 HLoadEliminationTable* table =
523 new(zone()) HLoadEliminationTable(zone(), &aliasing); 513 new(zone()) HLoadEliminationTable(zone(), &aliasing);
524 514
525 if (GLOBAL) { 515 if (GLOBAL) {
526 // Perform a global analysis. 516 // Perform a global analysis.
527 engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), table); 517 engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), table);
528 } else { 518 } else {
529 // Perform only local analysis. 519 // Perform only local analysis.
530 for (int i = 0; i < graph()->blocks()->length(); i++) { 520 for (int i = 0; i < graph()->blocks()->length(); i++) {
531 table->Kill(); 521 table->Kill();
532 engine.AnalyzeOneBlock(graph()->blocks()->at(i), table); 522 engine.AnalyzeOneBlock(graph()->blocks()->at(i), table);
533 } 523 }
534 } 524 }
535 } 525 }
536 526
537 } } // namespace v8::internal 527 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen-instructions.cc ('k') | src/hydrogen-representation-changes.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698