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

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

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