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

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

Issue 106973005: Improve load elimination handling of transitioning stores. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Added new cases to existing load elimination tests. Created 7 years 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 | « no previous file | test/mjsunit/compiler/load-elimination.js » ('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 25 matching lines...) Expand all
36 #define GLOBAL true 36 #define GLOBAL true
37 #define TRACE(x) if (FLAG_trace_load_elimination) PrintF x 37 #define TRACE(x) if (FLAG_trace_load_elimination) PrintF x
38 38
39 static const int kMaxTrackedFields = 16; 39 static const int kMaxTrackedFields = 16;
40 static const int kMaxTrackedObjects = 5; 40 static const int kMaxTrackedObjects = 5;
41 41
42 // An element in the field approximation list. 42 // An element in the field approximation list.
43 class HFieldApproximation : public ZoneObject { 43 class HFieldApproximation : public ZoneObject {
44 public: // Just a data blob. 44 public: // Just a data blob.
45 HValue* object_; 45 HValue* object_;
46 HLoadNamedField* last_load_;
47 HValue* last_value_; 46 HValue* last_value_;
48 HFieldApproximation* next_; 47 HFieldApproximation* next_;
49 48
50 // Recursively copy the entire linked list of field approximations. 49 // Recursively copy the entire linked list of field approximations.
51 HFieldApproximation* Copy(Zone* zone) { 50 HFieldApproximation* Copy(Zone* zone) {
52 if (this == NULL) return NULL; 51 if (this == NULL) return NULL;
53 HFieldApproximation* copy = new(zone) HFieldApproximation(); 52 HFieldApproximation* copy = new(zone) HFieldApproximation();
54 copy->object_ = this->object_; 53 copy->object_ = this->object_;
55 copy->last_load_ = this->last_load_;
56 copy->last_value_ = this->last_value_; 54 copy->last_value_ = this->last_value_;
57 copy->next_ = this->next_->Copy(zone); 55 copy->next_ = this->next_->Copy(zone);
58 return copy; 56 return copy;
59 } 57 }
60 }; 58 };
61 59
62 60
63 // The main datastructure used during load/store elimination. Each in-object 61 // The main datastructure used during load/store elimination. Each in-object
64 // field is tracked separately. For each field, store a list of known field 62 // field is tracked separately. For each field, store a list of known field
65 // values for known objects. 63 // values for known objects.
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 // which the load should be replaced. Otherwise, return {instr}. 188 // which the load should be replaced. Otherwise, return {instr}.
191 HValue* load(HLoadNamedField* instr) { 189 HValue* load(HLoadNamedField* instr) {
192 int field = FieldOf(instr->access()); 190 int field = FieldOf(instr->access());
193 if (field < 0) return instr; 191 if (field < 0) return instr;
194 192
195 HValue* object = instr->object()->ActualValue(); 193 HValue* object = instr->object()->ActualValue();
196 HFieldApproximation* approx = FindOrCreate(object, field); 194 HFieldApproximation* approx = FindOrCreate(object, field);
197 195
198 if (approx->last_value_ == NULL) { 196 if (approx->last_value_ == NULL) {
199 // Load is not redundant. Fill out a new entry. 197 // Load is not redundant. Fill out a new entry.
200 approx->last_load_ = instr;
201 approx->last_value_ = instr; 198 approx->last_value_ = instr;
202 return instr; 199 return instr;
203 } else { 200 } else {
204 // Eliminate the load. Reuse previously stored value or load instruction. 201 // Eliminate the load. Reuse previously stored value or load instruction.
205 return approx->last_value_; 202 return approx->last_value_;
206 } 203 }
207 } 204 }
208 205
209 // Process a store instruction, updating internal table state. If a previous 206 // Process a store instruction, updating internal table state. If a previous
210 // store to the same object and field makes this store redundant (e.g. because 207 // store to the same object and field makes this store redundant (e.g. because
211 // the stored values are the same), return NULL indicating that this store 208 // the stored values are the same), return NULL indicating that this store
212 // instruction is redundant. Otherwise, return {instr}. 209 // instruction is redundant. Otherwise, return {instr}.
213 HValue* store(HStoreNamedField* instr) { 210 HValue* store(HStoreNamedField* instr) {
214 int field = FieldOf(instr->access()); 211 int field = FieldOf(instr->access());
215 if (field < 0) return KillIfMisaligned(instr); 212 if (field < 0) return KillIfMisaligned(instr);
216 213
217 HValue* object = instr->object()->ActualValue(); 214 HValue* object = instr->object()->ActualValue();
218 HValue* value = instr->value(); 215 HValue* value = instr->value();
219 216
220 // Kill non-equivalent may-alias entries.
221 KillFieldInternal(object, field, value);
222 if (instr->has_transition()) { 217 if (instr->has_transition()) {
223 // A transition store alters the map of the object. 218 // A transition introduces a new field and alters the map of the object.
224 // TODO(titzer): remember the new map (a constant) for the object. 219 // Since the field in the object is new, it cannot alias existing entries.
220 // TODO(titzer): introduce a constant for the new map and remember it.
225 KillFieldInternal(object, FieldOf(JSObject::kMapOffset), NULL); 221 KillFieldInternal(object, FieldOf(JSObject::kMapOffset), NULL);
222 } else {
223 // Kill non-equivalent may-alias entries.
224 KillFieldInternal(object, field, value);
226 } 225 }
227 HFieldApproximation* approx = FindOrCreate(object, field); 226 HFieldApproximation* approx = FindOrCreate(object, field);
228 227
229 if (Equal(approx->last_value_, value)) { 228 if (Equal(approx->last_value_, value)) {
230 // The store is redundant because the field already has this value. 229 // The store is redundant because the field already has this value.
231 return NULL; 230 return NULL;
232 } else { 231 } else {
233 // The store is not redundant. Update the entry. 232 // The store is not redundant. Update the entry.
234 approx->last_load_ = NULL;
235 approx->last_value_ = value; 233 approx->last_value_ = value;
236 return instr; 234 return instr;
237 } 235 }
238 } 236 }
239 237
240 // Kill everything in this table. 238 // Kill everything in this table.
241 void Kill() { 239 void Kill() {
242 fields_.Rewind(0); 240 fields_.Rewind(0);
243 } 241 }
244 242
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 if (count >= kMaxTrackedObjects) { 305 if (count >= kMaxTrackedObjects) {
308 // Pull the last entry off the end and repurpose it for this object. 306 // Pull the last entry off the end and repurpose it for this object.
309 approx = ReuseLastApproximation(field); 307 approx = ReuseLastApproximation(field);
310 } else { 308 } else {
311 // Allocate a new entry. 309 // Allocate a new entry.
312 approx = new(zone_) HFieldApproximation(); 310 approx = new(zone_) HFieldApproximation();
313 } 311 }
314 312
315 // Insert the entry at the head of the list. 313 // Insert the entry at the head of the list.
316 approx->object_ = object; 314 approx->object_ = object;
317 approx->last_load_ = NULL;
318 approx->last_value_ = NULL; 315 approx->last_value_ = NULL;
319 approx->next_ = fields_[field]; 316 approx->next_ = fields_[field];
320 fields_[field] = approx; 317 fields_[field] = approx;
321 318
322 return approx; 319 return approx;
323 } 320 }
324 321
325 // Kill all entries for a given field that _may_ alias the given object 322 // Kill all entries for a given field that _may_ alias the given object
326 // and do _not_ have the given value. 323 // and do _not_ have the given value.
327 void KillFieldInternal(HValue* object, int field, HValue* value) { 324 void KillFieldInternal(HValue* object, int field, HValue* value) {
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 fields_.AddBlock(NULL, num_fields - fields_.length(), zone_); 387 fields_.AddBlock(NULL, num_fields - fields_.length(), zone_);
391 } 388 }
392 } 389 }
393 390
394 // Print this table to stdout. 391 // Print this table to stdout.
395 void Print() { 392 void Print() {
396 for (int i = 0; i < fields_.length(); i++) { 393 for (int i = 0; i < fields_.length(); i++) {
397 PrintF(" field %d: ", i); 394 PrintF(" field %d: ", i);
398 for (HFieldApproximation* a = fields_[i]; a != NULL; a = a->next_) { 395 for (HFieldApproximation* a = fields_[i]; a != NULL; a = a->next_) {
399 PrintF("[o%d =", a->object_->id()); 396 PrintF("[o%d =", a->object_->id());
400 if (a->last_load_ != NULL) PrintF(" L%d", a->last_load_->id());
401 if (a->last_value_ != NULL) PrintF(" v%d", a->last_value_->id()); 397 if (a->last_value_ != NULL) PrintF(" v%d", a->last_value_->id());
402 PrintF("] "); 398 PrintF("] ");
403 } 399 }
404 PrintF("\n"); 400 PrintF("\n");
405 } 401 }
406 } 402 }
407 403
408 Zone* zone_; 404 Zone* zone_;
409 ZoneList<HFieldApproximation*> fields_; 405 ZoneList<HFieldApproximation*> fields_;
410 HAliasAnalyzer* aliasing_; 406 HAliasAnalyzer* aliasing_;
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
501 } else { 497 } else {
502 // Perform only local analysis. 498 // Perform only local analysis.
503 for (int i = 0; i < graph()->blocks()->length(); i++) { 499 for (int i = 0; i < graph()->blocks()->length(); i++) {
504 table->Kill(); 500 table->Kill();
505 engine.AnalyzeOneBlock(graph()->blocks()->at(i), table); 501 engine.AnalyzeOneBlock(graph()->blocks()->at(i), table);
506 } 502 }
507 } 503 }
508 } 504 }
509 505
510 } } // namespace v8::internal 506 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « no previous file | test/mjsunit/compiler/load-elimination.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698