OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/load-elimination.h" | 5 #include "src/compiler/load-elimination.h" |
6 | 6 |
| 7 #include "src/compiler/js-graph.h" |
7 #include "src/compiler/node-properties.h" | 8 #include "src/compiler/node-properties.h" |
8 #include "src/compiler/simplified-operator.h" | 9 #include "src/compiler/simplified-operator.h" |
9 | 10 |
10 namespace v8 { | 11 namespace v8 { |
11 namespace internal { | 12 namespace internal { |
12 namespace compiler { | 13 namespace compiler { |
13 | 14 |
14 namespace { | 15 namespace { |
15 | 16 |
16 enum Aliasing { kNoAlias, kMayAlias, kMustAlias }; | 17 enum Aliasing { kNoAlias, kMayAlias, kMustAlias }; |
(...skipping 29 matching lines...) Expand all Loading... |
46 bool MayAlias(Node* a, Node* b) { return QueryAlias(a, b) != kNoAlias; } | 47 bool MayAlias(Node* a, Node* b) { return QueryAlias(a, b) != kNoAlias; } |
47 | 48 |
48 bool MustAlias(Node* a, Node* b) { return QueryAlias(a, b) == kMustAlias; } | 49 bool MustAlias(Node* a, Node* b) { return QueryAlias(a, b) == kMustAlias; } |
49 | 50 |
50 } // namespace | 51 } // namespace |
51 | 52 |
52 Reduction LoadElimination::Reduce(Node* node) { | 53 Reduction LoadElimination::Reduce(Node* node) { |
53 switch (node->opcode()) { | 54 switch (node->opcode()) { |
54 case IrOpcode::kCheckMaps: | 55 case IrOpcode::kCheckMaps: |
55 return ReduceCheckMaps(node); | 56 return ReduceCheckMaps(node); |
| 57 case IrOpcode::kEnsureWritableFastElements: |
| 58 return ReduceEnsureWritableFastElements(node); |
56 case IrOpcode::kTransitionElementsKind: | 59 case IrOpcode::kTransitionElementsKind: |
57 return ReduceTransitionElementsKind(node); | 60 return ReduceTransitionElementsKind(node); |
58 case IrOpcode::kLoadField: | 61 case IrOpcode::kLoadField: |
59 return ReduceLoadField(node); | 62 return ReduceLoadField(node); |
60 case IrOpcode::kStoreField: | 63 case IrOpcode::kStoreField: |
61 return ReduceStoreField(node); | 64 return ReduceStoreField(node); |
62 case IrOpcode::kLoadElement: | 65 case IrOpcode::kLoadElement: |
63 return ReduceLoadElement(node); | 66 return ReduceLoadElement(node); |
64 case IrOpcode::kStoreElement: | 67 case IrOpcode::kStoreElement: |
65 return ReduceStoreElement(node); | 68 return ReduceStoreElement(node); |
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 if (map == object_map) return Replace(effect); | 322 if (map == object_map) return Replace(effect); |
320 } | 323 } |
321 } | 324 } |
322 if (map_input_count == 1) { | 325 if (map_input_count == 1) { |
323 Node* const map0 = NodeProperties::GetValueInput(node, 1); | 326 Node* const map0 = NodeProperties::GetValueInput(node, 1); |
324 state = state->AddField(object, 0, map0, zone()); | 327 state = state->AddField(object, 0, map0, zone()); |
325 } | 328 } |
326 return UpdateState(node, state); | 329 return UpdateState(node, state); |
327 } | 330 } |
328 | 331 |
| 332 Reduction LoadElimination::ReduceEnsureWritableFastElements(Node* node) { |
| 333 Node* const object = NodeProperties::GetValueInput(node, 0); |
| 334 Node* const elements = NodeProperties::GetValueInput(node, 1); |
| 335 Node* const effect = NodeProperties::GetEffectInput(node); |
| 336 AbstractState const* state = node_states_.Get(effect); |
| 337 if (state == nullptr) return NoChange(); |
| 338 Node* fixed_array_map = jsgraph()->FixedArrayMapConstant(); |
| 339 if (Node* const elements_map = state->LookupField(elements, 0)) { |
| 340 // Check if the {elements} already have the fixed array map. |
| 341 if (elements_map == fixed_array_map) { |
| 342 ReplaceWithValue(node, elements, effect); |
| 343 return Replace(elements); |
| 344 } |
| 345 } |
| 346 // We know that the resulting elements have the fixed array map. |
| 347 state = state->AddField(node, 0, fixed_array_map, zone()); |
| 348 // Kill the previous elements on {object}. |
| 349 state = state->KillField(object, 2, zone()); |
| 350 // Add the new elements on {object}. |
| 351 state = state->AddField(object, 2, node, zone()); |
| 352 return UpdateState(node, state); |
| 353 } |
| 354 |
329 Reduction LoadElimination::ReduceTransitionElementsKind(Node* node) { | 355 Reduction LoadElimination::ReduceTransitionElementsKind(Node* node) { |
330 Node* const object = NodeProperties::GetValueInput(node, 0); | 356 Node* const object = NodeProperties::GetValueInput(node, 0); |
331 Node* const source_map = NodeProperties::GetValueInput(node, 1); | 357 Node* const source_map = NodeProperties::GetValueInput(node, 1); |
332 Node* const target_map = NodeProperties::GetValueInput(node, 2); | 358 Node* const target_map = NodeProperties::GetValueInput(node, 2); |
333 Node* const effect = NodeProperties::GetEffectInput(node); | 359 Node* const effect = NodeProperties::GetEffectInput(node); |
334 AbstractState const* state = node_states_.Get(effect); | 360 AbstractState const* state = node_states_.Get(effect); |
335 if (state == nullptr) return NoChange(); | 361 if (state == nullptr) return NoChange(); |
336 if (Node* const object_map = state->LookupField(object, 0)) { | 362 if (Node* const object_map = state->LookupField(object, 0)) { |
337 state = state->KillField(object, 0, zone()); | 363 state = state->KillField(object, 0, zone()); |
338 if (source_map == object_map) { | 364 if (source_map == object_map) { |
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
545 for (int i = 1; i < control->InputCount(); ++i) { | 571 for (int i = 1; i < control->InputCount(); ++i) { |
546 queue.push(node->InputAt(i)); | 572 queue.push(node->InputAt(i)); |
547 } | 573 } |
548 while (!queue.empty()) { | 574 while (!queue.empty()) { |
549 Node* const current = queue.front(); | 575 Node* const current = queue.front(); |
550 queue.pop(); | 576 queue.pop(); |
551 if (visited.find(current) == visited.end()) { | 577 if (visited.find(current) == visited.end()) { |
552 visited.insert(current); | 578 visited.insert(current); |
553 if (!current->op()->HasProperty(Operator::kNoWrite)) { | 579 if (!current->op()->HasProperty(Operator::kNoWrite)) { |
554 switch (current->opcode()) { | 580 switch (current->opcode()) { |
| 581 case IrOpcode::kEnsureWritableFastElements: { |
| 582 Node* const object = NodeProperties::GetValueInput(current, 0); |
| 583 Node* const elements = NodeProperties::GetValueInput(current, 1); |
| 584 state = state->KillField(elements, 0, zone()); |
| 585 state = state->KillField(object, 2, zone()); |
| 586 break; |
| 587 } |
| 588 case IrOpcode::kTransitionElementsKind: { |
| 589 Node* const object = NodeProperties::GetValueInput(current, 0); |
| 590 state = state->KillField(object, 0, zone()); |
| 591 state = state->KillField(object, 2, zone()); |
| 592 break; |
| 593 } |
555 case IrOpcode::kStoreField: { | 594 case IrOpcode::kStoreField: { |
556 FieldAccess const& access = FieldAccessOf(current->op()); | 595 FieldAccess const& access = FieldAccessOf(current->op()); |
557 Node* const object = NodeProperties::GetValueInput(current, 0); | 596 Node* const object = NodeProperties::GetValueInput(current, 0); |
558 int field_index = FieldIndexOf(access); | 597 int field_index = FieldIndexOf(access); |
559 if (field_index < 0) return empty_state(); | 598 if (field_index < 0) return empty_state(); |
560 state = state->KillField(object, field_index, zone()); | 599 state = state->KillField(object, field_index, zone()); |
561 break; | 600 break; |
562 } | 601 } |
563 case IrOpcode::kStoreElement: { | 602 case IrOpcode::kStoreElement: { |
564 Node* const object = NodeProperties::GetValueInput(current, 0); | 603 Node* const object = NodeProperties::GetValueInput(current, 0); |
565 Node* const index = NodeProperties::GetValueInput(current, 1); | 604 Node* const index = NodeProperties::GetValueInput(current, 1); |
566 state = state->KillElement(object, index, zone()); | 605 state = state->KillElement(object, index, zone()); |
567 break; | 606 break; |
568 } | 607 } |
| 608 case IrOpcode::kStoreBuffer: |
| 609 case IrOpcode::kStoreTypedElement: { |
| 610 // Doesn't affect anything we track with the state currently. |
| 611 break; |
| 612 } |
569 default: | 613 default: |
570 return empty_state(); | 614 return empty_state(); |
571 } | 615 } |
572 } | 616 } |
573 for (int i = 0; i < current->op()->EffectInputCount(); ++i) { | 617 for (int i = 0; i < current->op()->EffectInputCount(); ++i) { |
574 queue.push(NodeProperties::GetEffectInput(current, i)); | 618 queue.push(NodeProperties::GetEffectInput(current, i)); |
575 } | 619 } |
576 } | 620 } |
577 } | 621 } |
578 return state; | 622 return state; |
(...skipping 27 matching lines...) Expand all Loading... |
606 DCHECK_EQ(kTaggedBase, access.base_is_tagged); | 650 DCHECK_EQ(kTaggedBase, access.base_is_tagged); |
607 DCHECK_EQ(0, access.offset % kPointerSize); | 651 DCHECK_EQ(0, access.offset % kPointerSize); |
608 int field_index = access.offset / kPointerSize; | 652 int field_index = access.offset / kPointerSize; |
609 if (field_index >= static_cast<int>(kMaxTrackedFields)) return -1; | 653 if (field_index >= static_cast<int>(kMaxTrackedFields)) return -1; |
610 return field_index; | 654 return field_index; |
611 } | 655 } |
612 | 656 |
613 } // namespace compiler | 657 } // namespace compiler |
614 } // namespace internal | 658 } // namespace internal |
615 } // namespace v8 | 659 } // namespace v8 |
OLD | NEW |