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 |