| 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 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 205 return approx->last_value_; | 205 return approx->last_value_; |
| 206 } | 206 } |
| 207 } | 207 } |
| 208 | 208 |
| 209 // Process a store instruction, updating internal table state. If a previous | 209 // 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 | 210 // 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 | 211 // the stored values are the same), return NULL indicating that this store |
| 212 // instruction is redundant. Otherwise, return {instr}. | 212 // instruction is redundant. Otherwise, return {instr}. |
| 213 HValue* store(HStoreNamedField* instr) { | 213 HValue* store(HStoreNamedField* instr) { |
| 214 int field = FieldOf(instr->access()); | 214 int field = FieldOf(instr->access()); |
| 215 if (field < 0) return instr; | 215 if (field < 0) return KillIfMisaligned(instr); |
| 216 | 216 |
| 217 HValue* object = instr->object()->ActualValue(); | 217 HValue* object = instr->object()->ActualValue(); |
| 218 HValue* value = instr->value(); | 218 HValue* value = instr->value(); |
| 219 | 219 |
| 220 // Kill non-equivalent may-alias entries. | 220 // Kill non-equivalent may-alias entries. |
| 221 KillFieldInternal(object, field, value); | 221 KillFieldInternal(object, field, value); |
| 222 if (instr->has_transition()) { | 222 if (instr->has_transition()) { |
| 223 // A transition store alters the map of the object. | 223 // A transition store alters the map of the object. |
| 224 // TODO(titzer): remember the new map (a constant) for the object. | 224 // TODO(titzer): remember the new map (a constant) for the object. |
| 225 KillFieldInternal(object, FieldOf(JSObject::kMapOffset), NULL); | 225 KillFieldInternal(object, FieldOf(JSObject::kMapOffset), NULL); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 243 } | 243 } |
| 244 | 244 |
| 245 // Kill all entries matching the given offset. | 245 // Kill all entries matching the given offset. |
| 246 void KillOffset(int offset) { | 246 void KillOffset(int offset) { |
| 247 int field = FieldOf(offset); | 247 int field = FieldOf(offset); |
| 248 if (field >= 0 && field < fields_.length()) { | 248 if (field >= 0 && field < fields_.length()) { |
| 249 fields_[field] = NULL; | 249 fields_[field] = NULL; |
| 250 } | 250 } |
| 251 } | 251 } |
| 252 | 252 |
| 253 // Kill all entries aliasing the given store. |
| 254 void KillStore(HStoreNamedField* s) { |
| 255 int field = FieldOf(s->access()); |
| 256 if (field >= 0) { |
| 257 KillFieldInternal(s->object()->ActualValue(), field, s->value()); |
| 258 } else { |
| 259 KillIfMisaligned(s); |
| 260 } |
| 261 } |
| 262 |
| 263 // Kill multiple entries in the case of a misaligned store. |
| 264 HValue* KillIfMisaligned(HStoreNamedField* instr) { |
| 265 HObjectAccess access = instr->access(); |
| 266 if (access.IsInobject()) { |
| 267 int offset = access.offset(); |
| 268 if ((offset % kPointerSize) != 0) { |
| 269 // Kill the field containing the first word of the access. |
| 270 HValue* object = instr->object()->ActualValue(); |
| 271 int field = offset / kPointerSize; |
| 272 KillFieldInternal(object, field, NULL); |
| 273 |
| 274 // Kill the next field in case of overlap. |
| 275 int size = kPointerSize; |
| 276 if (access.representation().IsByte()) size = 1; |
| 277 else if (access.representation().IsInteger32()) size = 4; |
| 278 int next_field = (offset + size - 1) / kPointerSize; |
| 279 if (next_field != field) KillFieldInternal(object, next_field, NULL); |
| 280 } |
| 281 } |
| 282 return instr; |
| 283 } |
| 284 |
| 253 // Find an entry for the given object and field pair. | 285 // Find an entry for the given object and field pair. |
| 254 HFieldApproximation* Find(HValue* object, int field) { | 286 HFieldApproximation* Find(HValue* object, int field) { |
| 255 // Search for a field approximation for this object. | 287 // Search for a field approximation for this object. |
| 256 HFieldApproximation* approx = fields_[field]; | 288 HFieldApproximation* approx = fields_[field]; |
| 257 while (approx != NULL) { | 289 while (approx != NULL) { |
| 258 if (aliasing_->MustAlias(object, approx->object_)) return approx; | 290 if (aliasing_->MustAlias(object, approx->object_)) return approx; |
| 259 approx = approx->next_; | 291 approx = approx->next_; |
| 260 } | 292 } |
| 261 return NULL; | 293 return NULL; |
| 262 } | 294 } |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 } | 372 } |
| 341 | 373 |
| 342 // Compute the field index for the given object access; -1 if not tracked. | 374 // Compute the field index for the given object access; -1 if not tracked. |
| 343 int FieldOf(HObjectAccess access) { | 375 int FieldOf(HObjectAccess access) { |
| 344 return access.IsInobject() ? FieldOf(access.offset()) : -1; | 376 return access.IsInobject() ? FieldOf(access.offset()) : -1; |
| 345 } | 377 } |
| 346 | 378 |
| 347 // Compute the field index for the given in-object offset; -1 if not tracked. | 379 // Compute the field index for the given in-object offset; -1 if not tracked. |
| 348 int FieldOf(int offset) { | 380 int FieldOf(int offset) { |
| 349 if (offset >= kMaxTrackedFields * kPointerSize) return -1; | 381 if (offset >= kMaxTrackedFields * kPointerSize) return -1; |
| 350 ASSERT((offset % kPointerSize) == 0); // Assume aligned accesses. | 382 // TODO(titzer): track misaligned loads in a separate list? |
| 383 if ((offset % kPointerSize) != 0) return -1; // Ignore misaligned accesses. |
| 351 return offset / kPointerSize; | 384 return offset / kPointerSize; |
| 352 } | 385 } |
| 353 | 386 |
| 354 // Ensure internal storage for the given number of fields. | 387 // Ensure internal storage for the given number of fields. |
| 355 void EnsureFields(int num_fields) { | 388 void EnsureFields(int num_fields) { |
| 356 if (fields_.length() < num_fields) { | 389 if (fields_.length() < num_fields) { |
| 357 fields_.AddBlock(NULL, num_fields - fields_.length(), zone_); | 390 fields_.AddBlock(NULL, num_fields - fields_.length(), zone_); |
| 358 } | 391 } |
| 359 } | 392 } |
| 360 | 393 |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 423 } | 456 } |
| 424 if (maps_stored_) { | 457 if (maps_stored_) { |
| 425 table->KillOffset(JSObject::kMapOffset); | 458 table->KillOffset(JSObject::kMapOffset); |
| 426 } | 459 } |
| 427 if (elements_stored_) { | 460 if (elements_stored_) { |
| 428 table->KillOffset(JSObject::kElementsOffset); | 461 table->KillOffset(JSObject::kElementsOffset); |
| 429 } | 462 } |
| 430 | 463 |
| 431 // Kill non-agreeing fields for each store contained in these effects. | 464 // Kill non-agreeing fields for each store contained in these effects. |
| 432 for (int i = 0; i < stores_.length(); i++) { | 465 for (int i = 0; i < stores_.length(); i++) { |
| 433 HStoreNamedField* s = stores_[i]; | 466 table->KillStore(stores_[i]); |
| 434 int field = table->FieldOf(s->access()); | |
| 435 if (field >= 0) { | |
| 436 table->KillFieldInternal(s->object()->ActualValue(), field, s->value()); | |
| 437 } | |
| 438 } | 467 } |
| 439 } | 468 } |
| 440 | 469 |
| 441 // Union these effects with the other effects. | 470 // Union these effects with the other effects. |
| 442 void Union(HLoadEliminationEffects* that, Zone* zone) { | 471 void Union(HLoadEliminationEffects* that, Zone* zone) { |
| 443 maps_stored_ |= that->maps_stored_; | 472 maps_stored_ |= that->maps_stored_; |
| 444 fields_stored_ |= that->fields_stored_; | 473 fields_stored_ |= that->fields_stored_; |
| 445 elements_stored_ |= that->elements_stored_; | 474 elements_stored_ |= that->elements_stored_; |
| 446 for (int i = 0; i < that->stores_.length(); i++) { | 475 for (int i = 0; i < that->stores_.length(); i++) { |
| 447 stores_.Add(that->stores_[i], zone); | 476 stores_.Add(that->stores_[i], zone); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 472 } else { | 501 } else { |
| 473 // Perform only local analysis. | 502 // Perform only local analysis. |
| 474 for (int i = 0; i < graph()->blocks()->length(); i++) { | 503 for (int i = 0; i < graph()->blocks()->length(); i++) { |
| 475 table->Kill(); | 504 table->Kill(); |
| 476 engine.AnalyzeOneBlock(graph()->blocks()->at(i), table); | 505 engine.AnalyzeOneBlock(graph()->blocks()->at(i), table); |
| 477 } | 506 } |
| 478 } | 507 } |
| 479 } | 508 } |
| 480 | 509 |
| 481 } } // namespace v8::internal | 510 } } // namespace v8::internal |
| OLD | NEW |