| OLD | NEW | 
|---|
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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  Loading... | 
| 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 | 
| OLD | NEW | 
|---|