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

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

Issue 2304093002: [turbofan] Make field indices explicit for LoadElimination. (Closed)
Patch Set: Created 4 years, 3 months 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
« no previous file with comments | « src/compiler/load-elimination.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/common-operator.h" 7 #include "src/compiler/common-operator.h"
8 #include "src/compiler/js-graph.h" 8 #include "src/compiler/js-graph.h"
9 #include "src/compiler/node-properties.h" 9 #include "src/compiler/node-properties.h"
10 #include "src/compiler/simplified-operator.h" 10 #include "src/compiler/simplified-operator.h"
(...skipping 487 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 state = state->AddCheck(node, zone()); 498 state = state->AddCheck(node, zone());
499 return UpdateState(node, state); 499 return UpdateState(node, state);
500 } 500 }
501 501
502 Reduction LoadElimination::ReduceCheckMaps(Node* node) { 502 Reduction LoadElimination::ReduceCheckMaps(Node* node) {
503 Node* const object = NodeProperties::GetValueInput(node, 0); 503 Node* const object = NodeProperties::GetValueInput(node, 0);
504 Node* const effect = NodeProperties::GetEffectInput(node); 504 Node* const effect = NodeProperties::GetEffectInput(node);
505 AbstractState const* state = node_states_.Get(effect); 505 AbstractState const* state = node_states_.Get(effect);
506 if (state == nullptr) return NoChange(); 506 if (state == nullptr) return NoChange();
507 int const map_input_count = node->op()->ValueInputCount() - 1; 507 int const map_input_count = node->op()->ValueInputCount() - 1;
508 if (Node* const object_map = state->LookupField(object, 0)) { 508 if (Node* const object_map =
509 state->LookupField(object, FieldIndexOf(HeapObject::kMapOffset))) {
509 for (int i = 0; i < map_input_count; ++i) { 510 for (int i = 0; i < map_input_count; ++i) {
510 Node* map = NodeProperties::GetValueInput(node, 1 + i); 511 Node* map = NodeProperties::GetValueInput(node, 1 + i);
511 if (map == object_map) return Replace(effect); 512 if (map == object_map) return Replace(effect);
512 } 513 }
513 } 514 }
514 if (map_input_count == 1) { 515 if (map_input_count == 1) {
515 Node* const map0 = NodeProperties::GetValueInput(node, 1); 516 Node* const map0 = NodeProperties::GetValueInput(node, 1);
516 state = state->AddField(object, 0, map0, zone()); 517 state = state->AddField(object, FieldIndexOf(HeapObject::kMapOffset), map0,
518 zone());
517 } 519 }
518 return UpdateState(node, state); 520 return UpdateState(node, state);
519 } 521 }
520 522
521 Reduction LoadElimination::ReduceEnsureWritableFastElements(Node* node) { 523 Reduction LoadElimination::ReduceEnsureWritableFastElements(Node* node) {
522 Node* const object = NodeProperties::GetValueInput(node, 0); 524 Node* const object = NodeProperties::GetValueInput(node, 0);
523 Node* const elements = NodeProperties::GetValueInput(node, 1); 525 Node* const elements = NodeProperties::GetValueInput(node, 1);
524 Node* const effect = NodeProperties::GetEffectInput(node); 526 Node* const effect = NodeProperties::GetEffectInput(node);
525 AbstractState const* state = node_states_.Get(effect); 527 AbstractState const* state = node_states_.Get(effect);
526 if (state == nullptr) return NoChange(); 528 if (state == nullptr) return NoChange();
527 Node* fixed_array_map = jsgraph()->FixedArrayMapConstant(); 529 Node* fixed_array_map = jsgraph()->FixedArrayMapConstant();
528 if (Node* const elements_map = state->LookupField(elements, 0)) { 530 if (Node* const elements_map =
531 state->LookupField(elements, FieldIndexOf(HeapObject::kMapOffset))) {
529 // Check if the {elements} already have the fixed array map. 532 // Check if the {elements} already have the fixed array map.
530 if (elements_map == fixed_array_map) { 533 if (elements_map == fixed_array_map) {
531 ReplaceWithValue(node, elements, effect); 534 ReplaceWithValue(node, elements, effect);
532 return Replace(elements); 535 return Replace(elements);
533 } 536 }
534 } 537 }
535 // We know that the resulting elements have the fixed array map. 538 // We know that the resulting elements have the fixed array map.
536 state = state->AddField(node, 0, fixed_array_map, zone()); 539 state = state->AddField(node, FieldIndexOf(HeapObject::kMapOffset),
540 fixed_array_map, zone());
537 // Kill the previous elements on {object}. 541 // Kill the previous elements on {object}.
538 state = state->KillField(object, 2, zone()); 542 state =
543 state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), zone());
539 // Add the new elements on {object}. 544 // Add the new elements on {object}.
540 state = state->AddField(object, 2, node, zone()); 545 state = state->AddField(object, FieldIndexOf(JSObject::kElementsOffset), node,
546 zone());
541 return UpdateState(node, state); 547 return UpdateState(node, state);
542 } 548 }
543 549
544 Reduction LoadElimination::ReduceMaybeGrowFastElements(Node* node) { 550 Reduction LoadElimination::ReduceMaybeGrowFastElements(Node* node) {
545 GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op()); 551 GrowFastElementsFlags flags = GrowFastElementsFlagsOf(node->op());
546 Node* const object = NodeProperties::GetValueInput(node, 0); 552 Node* const object = NodeProperties::GetValueInput(node, 0);
547 Node* const effect = NodeProperties::GetEffectInput(node); 553 Node* const effect = NodeProperties::GetEffectInput(node);
548 AbstractState const* state = node_states_.Get(effect); 554 AbstractState const* state = node_states_.Get(effect);
549 if (state == nullptr) return NoChange(); 555 if (state == nullptr) return NoChange();
550 if (flags & GrowFastElementsFlag::kDoubleElements) { 556 if (flags & GrowFastElementsFlag::kDoubleElements) {
551 // We know that the resulting elements have the fixed double array map. 557 // We know that the resulting elements have the fixed double array map.
552 Node* fixed_double_array_map = jsgraph()->FixedDoubleArrayMapConstant(); 558 Node* fixed_double_array_map = jsgraph()->FixedDoubleArrayMapConstant();
553 state = state->AddField(node, 0, fixed_double_array_map, zone()); 559 state = state->AddField(node, FieldIndexOf(HeapObject::kMapOffset),
560 fixed_double_array_map, zone());
554 } else { 561 } else {
555 // We know that the resulting elements have the fixed array map. 562 // We know that the resulting elements have the fixed array map.
556 Node* fixed_array_map = jsgraph()->FixedArrayMapConstant(); 563 Node* fixed_array_map = jsgraph()->FixedArrayMapConstant();
557 state = state->AddField(node, 0, fixed_array_map, zone()); 564 state = state->AddField(node, FieldIndexOf(HeapObject::kMapOffset),
565 fixed_array_map, zone());
558 } 566 }
559 if (flags & GrowFastElementsFlag::kArrayObject) { 567 if (flags & GrowFastElementsFlag::kArrayObject) {
560 // Kill the previous Array::length on {object}. 568 // Kill the previous Array::length on {object}.
561 state = state->KillField(object, 3, zone()); 569 state =
570 state->KillField(object, FieldIndexOf(JSArray::kLengthOffset), zone());
562 } 571 }
563 // Kill the previous elements on {object}. 572 // Kill the previous elements on {object}.
564 state = state->KillField(object, 2, zone()); 573 state =
574 state->KillField(object, FieldIndexOf(JSObject::kElementsOffset), zone());
565 // Add the new elements on {object}. 575 // Add the new elements on {object}.
566 state = state->AddField(object, 2, node, zone()); 576 state = state->AddField(object, FieldIndexOf(JSObject::kElementsOffset), node,
577 zone());
567 return UpdateState(node, state); 578 return UpdateState(node, state);
568 } 579 }
569 580
570 Reduction LoadElimination::ReduceTransitionElementsKind(Node* node) { 581 Reduction LoadElimination::ReduceTransitionElementsKind(Node* node) {
571 Node* const object = NodeProperties::GetValueInput(node, 0); 582 Node* const object = NodeProperties::GetValueInput(node, 0);
572 Node* const source_map = NodeProperties::GetValueInput(node, 1); 583 Node* const source_map = NodeProperties::GetValueInput(node, 1);
573 Node* const target_map = NodeProperties::GetValueInput(node, 2); 584 Node* const target_map = NodeProperties::GetValueInput(node, 2);
574 Node* const effect = NodeProperties::GetEffectInput(node); 585 Node* const effect = NodeProperties::GetEffectInput(node);
575 AbstractState const* state = node_states_.Get(effect); 586 AbstractState const* state = node_states_.Get(effect);
576 if (state == nullptr) return NoChange(); 587 if (state == nullptr) return NoChange();
577 if (Node* const object_map = state->LookupField(object, 0)) { 588 if (Node* const object_map =
589 state->LookupField(object, FieldIndexOf(HeapObject::kMapOffset))) {
578 if (target_map == object_map) { 590 if (target_map == object_map) {
579 // The {object} already has the {target_map}, so this TransitionElements 591 // The {object} already has the {target_map}, so this TransitionElements
580 // {node} is fully redundant (independent of what {source_map} is). 592 // {node} is fully redundant (independent of what {source_map} is).
581 return Replace(effect); 593 return Replace(effect);
582 } 594 }
583 state = state->KillField(object, 0, zone()); 595 state =
596 state->KillField(object, FieldIndexOf(HeapObject::kMapOffset), zone());
584 if (source_map == object_map) { 597 if (source_map == object_map) {
585 state = state->AddField(object, 0, target_map, zone()); 598 state = state->AddField(object, FieldIndexOf(HeapObject::kMapOffset),
599 target_map, zone());
586 } 600 }
587 } else { 601 } else {
588 state = state->KillField(object, 0, zone()); 602 state =
603 state->KillField(object, FieldIndexOf(HeapObject::kMapOffset), zone());
589 } 604 }
590 ElementsTransition transition = ElementsTransitionOf(node->op()); 605 ElementsTransition transition = ElementsTransitionOf(node->op());
591 switch (transition) { 606 switch (transition) {
592 case ElementsTransition::kFastTransition: 607 case ElementsTransition::kFastTransition:
593 break; 608 break;
594 case ElementsTransition::kSlowTransition: 609 case ElementsTransition::kSlowTransition:
595 // Kill the elements as well. 610 // Kill the elements as well.
596 state = state->KillField(object, 2, zone()); 611 state = state->KillField(object, FieldIndexOf(JSObject::kElementsOffset),
612 zone());
597 break; 613 break;
598 } 614 }
599 return UpdateState(node, state); 615 return UpdateState(node, state);
600 } 616 }
601 617
602 Reduction LoadElimination::ReduceLoadField(Node* node) { 618 Reduction LoadElimination::ReduceLoadField(Node* node) {
603 FieldAccess const& access = FieldAccessOf(node->op()); 619 FieldAccess const& access = FieldAccessOf(node->op());
604 Node* const object = NodeProperties::GetValueInput(node, 0); 620 Node* const object = NodeProperties::GetValueInput(node, 0);
605 Node* const effect = NodeProperties::GetEffectInput(node); 621 Node* const effect = NodeProperties::GetEffectInput(node);
606 Node* const control = NodeProperties::GetControlInput(node); 622 Node* const control = NodeProperties::GetControlInput(node);
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 } 821 }
806 while (!queue.empty()) { 822 while (!queue.empty()) {
807 Node* const current = queue.front(); 823 Node* const current = queue.front();
808 queue.pop(); 824 queue.pop();
809 if (visited.find(current) == visited.end()) { 825 if (visited.find(current) == visited.end()) {
810 visited.insert(current); 826 visited.insert(current);
811 if (!current->op()->HasProperty(Operator::kNoWrite)) { 827 if (!current->op()->HasProperty(Operator::kNoWrite)) {
812 switch (current->opcode()) { 828 switch (current->opcode()) {
813 case IrOpcode::kEnsureWritableFastElements: { 829 case IrOpcode::kEnsureWritableFastElements: {
814 Node* const object = NodeProperties::GetValueInput(current, 0); 830 Node* const object = NodeProperties::GetValueInput(current, 0);
815 state = state->KillField(object, 2, zone()); 831 state = state->KillField(
832 object, FieldIndexOf(JSObject::kElementsOffset), zone());
816 break; 833 break;
817 } 834 }
818 case IrOpcode::kMaybeGrowFastElements: { 835 case IrOpcode::kMaybeGrowFastElements: {
819 GrowFastElementsFlags flags = 836 GrowFastElementsFlags flags =
820 GrowFastElementsFlagsOf(current->op()); 837 GrowFastElementsFlagsOf(current->op());
821 Node* const object = NodeProperties::GetValueInput(current, 0); 838 Node* const object = NodeProperties::GetValueInput(current, 0);
822 state = state->KillField(object, 2, zone()); 839 state = state->KillField(
840 object, FieldIndexOf(JSObject::kElementsOffset), zone());
823 if (flags & GrowFastElementsFlag::kArrayObject) { 841 if (flags & GrowFastElementsFlag::kArrayObject) {
824 state = state->KillField(object, 3, zone()); 842 state = state->KillField(
843 object, FieldIndexOf(JSArray::kLengthOffset), zone());
825 } 844 }
826 break; 845 break;
827 } 846 }
828 case IrOpcode::kTransitionElementsKind: { 847 case IrOpcode::kTransitionElementsKind: {
829 Node* const object = NodeProperties::GetValueInput(current, 0); 848 Node* const object = NodeProperties::GetValueInput(current, 0);
830 state = state->KillField(object, 0, zone()); 849 state = state->KillField(
831 state = state->KillField(object, 2, zone()); 850 object, FieldIndexOf(HeapObject::kMapOffset), zone());
851 state = state->KillField(
852 object, FieldIndexOf(JSObject::kElementsOffset), zone());
832 break; 853 break;
833 } 854 }
834 case IrOpcode::kStoreField: { 855 case IrOpcode::kStoreField: {
835 FieldAccess const& access = FieldAccessOf(current->op()); 856 FieldAccess const& access = FieldAccessOf(current->op());
836 Node* const object = NodeProperties::GetValueInput(current, 0); 857 Node* const object = NodeProperties::GetValueInput(current, 0);
837 int field_index = FieldIndexOf(access); 858 int field_index = FieldIndexOf(access);
838 if (field_index < 0) return empty_state(); 859 if (field_index < 0) return empty_state();
839 state = state->KillField(object, field_index, zone()); 860 state = state->KillField(object, field_index, zone());
840 break; 861 break;
841 } 862 }
(...skipping 14 matching lines...) Expand all
856 } 877 }
857 for (int i = 0; i < current->op()->EffectInputCount(); ++i) { 878 for (int i = 0; i < current->op()->EffectInputCount(); ++i) {
858 queue.push(NodeProperties::GetEffectInput(current, i)); 879 queue.push(NodeProperties::GetEffectInput(current, i));
859 } 880 }
860 } 881 }
861 } 882 }
862 return state; 883 return state;
863 } 884 }
864 885
865 // static 886 // static
887 int LoadElimination::FieldIndexOf(int offset) {
888 DCHECK_EQ(0, offset % kPointerSize);
889 int field_index = offset / kPointerSize;
890 if (field_index >= static_cast<int>(kMaxTrackedFields)) return -1;
891 return field_index;
892 }
893
894 // static
866 int LoadElimination::FieldIndexOf(FieldAccess const& access) { 895 int LoadElimination::FieldIndexOf(FieldAccess const& access) {
867 MachineRepresentation rep = access.machine_type.representation(); 896 MachineRepresentation rep = access.machine_type.representation();
868 switch (rep) { 897 switch (rep) {
869 case MachineRepresentation::kNone: 898 case MachineRepresentation::kNone:
870 case MachineRepresentation::kBit: 899 case MachineRepresentation::kBit:
871 UNREACHABLE(); 900 UNREACHABLE();
872 break; 901 break;
873 case MachineRepresentation::kWord32: 902 case MachineRepresentation::kWord32:
874 case MachineRepresentation::kWord64: 903 case MachineRepresentation::kWord64:
875 if (rep != MachineType::PointerRepresentation()) { 904 if (rep != MachineType::PointerRepresentation()) {
876 return -1; // We currently only track pointer size fields. 905 return -1; // We currently only track pointer size fields.
877 } 906 }
878 break; 907 break;
879 case MachineRepresentation::kWord8: 908 case MachineRepresentation::kWord8:
880 case MachineRepresentation::kWord16: 909 case MachineRepresentation::kWord16:
881 case MachineRepresentation::kFloat32: 910 case MachineRepresentation::kFloat32:
882 return -1; // Currently untracked. 911 return -1; // Currently untracked.
883 case MachineRepresentation::kFloat64: 912 case MachineRepresentation::kFloat64:
884 case MachineRepresentation::kSimd128: 913 case MachineRepresentation::kSimd128:
885 return -1; // Currently untracked. 914 return -1; // Currently untracked.
886 case MachineRepresentation::kTaggedSigned: 915 case MachineRepresentation::kTaggedSigned:
887 case MachineRepresentation::kTaggedPointer: 916 case MachineRepresentation::kTaggedPointer:
888 case MachineRepresentation::kTagged: 917 case MachineRepresentation::kTagged:
889 // TODO(bmeurer): Check that we never do overlapping load/stores of 918 // TODO(bmeurer): Check that we never do overlapping load/stores of
890 // individual parts of Float64/Simd128 values. 919 // individual parts of Float64/Simd128 values.
891 break; 920 break;
892 } 921 }
893 DCHECK_EQ(kTaggedBase, access.base_is_tagged); 922 DCHECK_EQ(kTaggedBase, access.base_is_tagged);
894 DCHECK_EQ(0, access.offset % kPointerSize); 923 return FieldIndexOf(access.offset);
895 int field_index = access.offset / kPointerSize;
896 if (field_index >= static_cast<int>(kMaxTrackedFields)) return -1;
897 return field_index;
898 } 924 }
899 925
900 CommonOperatorBuilder* LoadElimination::common() const { 926 CommonOperatorBuilder* LoadElimination::common() const {
901 return jsgraph()->common(); 927 return jsgraph()->common();
902 } 928 }
903 929
904 Graph* LoadElimination::graph() const { return jsgraph()->graph(); } 930 Graph* LoadElimination::graph() const { return jsgraph()->graph(); }
905 931
906 } // namespace compiler 932 } // namespace compiler
907 } // namespace internal 933 } // namespace internal
908 } // namespace v8 934 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/load-elimination.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698